Рабочее решение проблемы изменения размера листа
Фон
В статье “Добавление OLE-рамок” мы объяснили, как добавить OLE-рамку в презентацию PowerPoint с использованием Aspose.Slides для C++. Чтобы учесть проблему изменения объекта, мы назначили изображение листа в выбранной области OLE-объектной рамки диаграммы. В выходной презентации при двойном клике на OLE-объектную рамку, показывающую изображение листа, активируется диаграмма Excel. Конечные пользователи могут вносить любые необходимые изменения в фактическую книгу Excel, а затем вернуться к соответствующему слайду, щелкнув вне активной книги Excel. Размер OLE-объектной рамки изменится, когда пользователь вернется к слайду. Фактор изменения размера будет различаться для различных размеров OLE-объектной рамки и встроенной книги Excel.
Причина изменения размера
Поскольку книга Excel имеет свой собственный размер окна, она пытается сохранить свой исходный размер при первой активации. С другой стороны, OLE-объектная рамка будет иметь свой собственный размер. Согласно данным Microsoft, при активации книги Excel Excel и PowerPoint согласуют размер и обеспечивают правильные пропорции в рамках операции встраивания. На основе различий в размере окон Excel и размере / позиции OLE-объектной рамки происходит изменение размера.
Рабочее решение
Существует два возможных решения для избежания эффекта изменения размера.
- Измените размер OLE-рамки в PPT, чтобы он соответствовал размеру по высоте/ширине желаемого числа строк/столбцов в OLE-рамке.
- Сохраняя постоянный размер OLE-рамки, измените размер участвующих строк/столбцов, чтобы они вписывались в выбранный размер OLE-рамки.
Изменение размера OLE-рамки в соответствии с выбранными строками/столбцами листа
В этом подходе мы научимся устанавливать размер OLE-рамки встроенной книги Excel, равный совокупному размеру числа участвующих строк и столбцов в листе Excel.
Пример
Предположим, мы определили шаблонный Excel-лист и хотим добавить его в презентацию как OLE-рамку. В этом сценарии размер OLE-объектной рамки будет сначала рассчитан на основе совокупной высоты строк и ширины столбцов участвующих строк и столбцов книги. Затем мы установим размер OLE-рамки на это рассчитанное значение. Чтобы избежать сообщения Встроенный объект для OLE-рамки в PowerPoint, мы также получим изображение желаемых частей строк и столбцов в книге и установим его как изображение OLE-рамки.
auto workbookDesigner = Aspose::Cells::Factory::CreateIWorkbookDesigner();
workbookDesigner->SetIWorkbook(Aspose::Cells::Factory::CreateIWorkbook(new Aspose::Cells::Systems::String("d:/AsposeTest.xls")));
System::SharedPtr<IPresentation> presentation = System::MakeObject<Presentation>(u"d:/AsposeTest.ppt");
System::SharedPtr<ISlide> slide = presentation->get_Slides()->idx_get(0);
AddOleFrame(slide, 0, 15, 0, 3, 0, 300, 1100, 0, 0, presentation, workbookDesigner, true, 0, 0);
System::String fileName = u"d:/AsposeTest_Ole.ppt";
presentation->Save(fileName, Export::SaveFormat::Pptx);
System::Drawing::Size SetOleAccordingToSelectedRowsColumns(intrusive_ptr<Aspose::Cells::IWorkbook> workbook, int32_t startRow, int32_t endRow, int32_t startCol, int32_t endCol, int32_t dataSheetIdx)
{
intrusive_ptr<Aspose::Cells::IWorksheet> work = workbook->GetIWorksheets()->GetObjectByIndex(dataSheetIdx);
double actualHeight = 0, actualWidth = 0;
for (int32_t i = startRow; i <= endRow; i++)
{
actualHeight += work->GetICells()->GetRowHeightInch(i);
}
for (int32_t i = startCol; i <= endCol; i++)
{
actualWidth += work->GetICells()->GetColumnWidthInch(i);
}
// Установка новой высоты строки и ширины столбца
return System::Drawing::Size((int32_t)(System::Math::Round(actualWidth, 2) * 576), (int32_t)(System::Math::Round(actualHeight, 2) * 576));
}
void AddOleFrame(System::SharedPtr<ISlide> slide, int32_t startRow, int32_t endRow,
int32_t startCol, int32_t endCol, int32_t dataSheetIdx, int32_t x, int32_t y,
double OleWidth, double OleHeight, System::SharedPtr<IPresentation> presentation,
intrusive_ptr<Aspose::Cells::IWorkbookDesigner> workbookDesigner,
bool onePagePerSheet, int32_t outputWidth, int32_t outputHeight)
{
std::wstring tempFileName = System::IO::Path::GetTempFileName_().ToWCS();
if (startRow == 0)
{
startRow++;
endRow++;
}
// Установка активного индекса листа книги
workbookDesigner->GetIWorkbook()->GetIWorksheets()->SetActiveSheetIndex(dataSheetIdx);
// Получение книги и выбранного листа
intrusive_ptr<Aspose::Cells::IWorkbook> workbook = workbookDesigner->GetIWorkbook();
intrusive_ptr<Aspose::Cells::IWorksheet> work = workbook->GetIWorksheets()->GetObjectByIndex(dataSheetIdx);
// Установка размера OLE в соответствии с выбранными строками и столбцами
System::Drawing::Size SlideOleSize = SetOleAccordingToSelectedRowsColumns(workbook, startRow, endRow, startCol, endCol, dataSheetIdx);
OleWidth = SlideOleSize.get_Width();
OleHeight = SlideOleSize.get_Height();
// Установка размера OLE в книге
workbook->GetIWorksheets()->SetOleSize(startRow, endRow, startCol, endCol);
workbook->GetIWorksheets()->GetObjectByIndex(0)->SetGridlinesVisible(false);
// Установка параметров изображения для получения изображения листа
intrusive_ptr<Aspose::Cells::Rendering::IImageOrPrintOptions> imageOrPrintOptions = Aspose::Cells::Factory::CreateIImageOrPrintOptions();
imageOrPrintOptions->SetImageFormat(Aspose::Cells::Systems::Drawing::Imaging::ImageFormat::GetBmp());
imageOrPrintOptions->SetOnePagePerSheet(onePagePerSheet);
intrusive_ptr<Aspose::Cells::Rendering::ISheetRender> render = Aspose::Cells::Factory::CreateISheetRender(workbookDesigner->GetIWorkbook()->GetIWorksheets()->GetObjectByIndex(dataSheetIdx), imageOrPrintOptions);
tempFileName.append(L".bmp");
render->ToImage(0, new String(tempFileName.c_str()));
System::String slidesTempFileName = System::String::FromWCS(tempFileName);
System::SharedPtr<System::Drawing::Image> image = ScaleImage(System::Drawing::Image::FromFile(slidesTempFileName), outputWidth, outputHeight);
System::String newTempFileName = slidesTempFileName.Replace(u".tmp", u".tmp1");
image->Save(newTempFileName, System::Drawing::Imaging::ImageFormat::get_Bmp());
// Добавление изображения в коллекцию изображений слайда
auto ppImage = presentation->get_Images()->AddImage(System::IO::File::ReadAllBytes(newTempFileName));
// Сохранение книги в поток и копирование в массив байтов
System::SharedPtr<System::IO::Stream> mstream = ToSlidesMemoryStream(workbook->SaveToStream());
System::ArrayPtr<uint8_t> chartOleData = System::MakeArray<uint8_t>(mstream->get_Length(), 0);
mstream->set_Position(0);
mstream->Read(chartOleData, 0, chartOleData->get_Length());
// Добавление OLE-объектной рамки
System::SharedPtr<OleEmbeddedDataInfo> dataInfo = System::MakeObject<OleEmbeddedDataInfo>(chartOleData, u"xls");
System::SharedPtr<IOleObjectFrame> oleObjectFrame = slide->get_Shapes()->AddOleObjectFrame(x, y, OleWidth, OleHeight, dataInfo);
// Установка изображения OLE-рамки и альтернативного текста
oleObjectFrame->get_SubstitutePictureFormat()->get_Picture()->set_Image(ppImage);
oleObjectFrame->set_AlternativeText(System::String(u"изображение") + ppImage);
}
System::SharedPtr<System::IO::MemoryStream> ToSlidesMemoryStream(intrusive_ptr<Aspose::Cells::Systems::IO::MemoryStream> inputStream)
{
System::ArrayPtr<uint8_t> outputBuffer = System::MakeArray<uint8_t>(inputStream->GetLength(), inputStream->GetBuffer()->ArrayPoint());
auto outputStream = System::MakeObject<System::IO::MemoryStream>(outputBuffer);
return outputStream;
}
System::SharedPtr<System::Drawing::Image> ScaleImage(System::SharedPtr<System::Drawing::Image> image, int32_t outputWidth, int32_t outputHeight)
{
if (outputWidth == 0 && outputHeight == 0)
{
outputWidth = image->get_Width();
outputHeight = image->get_Height();
}
System::SharedPtr<System::Drawing::Bitmap> outputImage = System::MakeObject<System::Drawing::Bitmap>(outputWidth, outputHeight, image->get_PixelFormat());
outputImage->SetResolution(image->get_HorizontalResolution(), image->get_VerticalResolution());
System::SharedPtr<System::Drawing::Graphics> graphics = System::Drawing::Graphics::FromImage(outputImage);
graphics->set_InterpolationMode(System::Drawing::Drawing2D::InterpolationMode::HighQualityBicubic);
System::Drawing::Rectangle srcDestRect(0, 0, outputWidth, outputHeight);
graphics->DrawImage(image, srcDestRect, srcDestRect, System::Drawing::GraphicsUnit::Pixel);
graphics->Dispose();
return outputImage;
}
Изменение высоты строк и ширины столбцов листа в соответствии с размером OLE-рамки
В этом подходе мы научимся изменять размеры высоты участвуемых строк и ширины участвующих столбцов в соответствии с заданным размером OLE-рамки
Пример
Предположим, мы определили шаблонный Excel-лист и хотим добавить его в презентацию как OLE-рамку. В этом сценарии мы установим размер OLE-рамки и изменим размер строк и столбцов, участвующих в области OLE-рамки. Затем мы сохраним книгу в потоке, чтобы сохранить изменения и преобразовать её в массив байтов для добавления в OLE-рамку. Чтобы избежать сообщения Встроенный объект для OLE-рамки в PowerPoint, мы также получим изображение желаемых частей строк и столбцов в книге и установим его как изображение OLE-рамки.
auto workbookDesigner = Aspose::Cells::Factory::CreateIWorkbookDesigner();
workbookDesigner->SetIWorkbook(Aspose::Cells::Factory::CreateIWorkbook(new Aspose::Cells::Systems::String("d:/AsposeTest.xls")));
System::SharedPtr<IPresentation> presentation = System::MakeObject<Presentation>(u"d:/AsposeTest.ppt");
System::SharedPtr<ISlide> slide = presentation->get_Slides()->idx_get(0);
AddOleFrame(slide, 0, 15, 0, 3, 0, 300, 1100, 0, 0, presentation, workbookDesigner, true, 0, 0);
System::String fileName = u"d:/AsposeTest_Ole.ppt";
presentation->Save(fileName, Export::SaveFormat::Pptx);
void SetOleAccordingToCustomHeightWidth(intrusive_ptr<Aspose::Cells::IWorkbook> workbook, int32_t startRow, int32_t endRow, int32_t startCol, int32_t endCol, double slideWidth, double slideHeight, int32_t dataSheetIdx)
{
auto work = workbook->GetIWorksheets()->GetObjectByIndex(dataSheetIdx);
double actualHeight = 0, actualWidth = 0;
double newHeight = slideHeight;
double newWidth = slideWidth;
double tem = 0;
double newTem = 0;
for (int32_t i = startRow; i <= endRow; i++)
{
actualHeight += work->GetICells()->GetRowHeightInch(i);
}
for (int32_t i = startCol; i <= endCol; i++)
{
actualWidth += work->GetICells()->GetColumnWidthInch(i);
}
// Установка новой высоты строк и ширины столбцов
for (int32_t i = startRow; i <= endRow; i++)
{
tem = work->GetICells()->GetRowHeightInch(i);
newTem = (tem / actualHeight) * newHeight;
work->GetICells()->SetRowHeightInch(i, newTem);
}
for (int32_t i = startCol; i <= endCol; i++)
{
tem = work->GetICells()->GetColumnWidthInch(i);
newTem = (tem / actualWidth) * newWidth;
work->GetICells()->SetColumnWidthInch(i, newTem);
}
}
void AddOleFrame(System::SharedPtr<ISlide> slide, int32_t startRow, int32_t endRow,
int32_t startCol, int32_t endCol, int32_t dataSheetIdx, int32_t x, int32_t y,
double OleWidth, double OleHeight, System::SharedPtr<IPresentation> presentation,
intrusive_ptr<Aspose::Cells::IWorkbookDesigner> workbookDesigner,
bool onePagePerSheet, int32_t outputWidth, int32_t outputHeight)
{
std::wstring tempFileName = System::IO::Path::GetTempFileName_().ToWCS();
if (startRow == 0)
{
startRow++;
endRow++;
}
// Установка активного индекса листа книги
workbookDesigner->GetIWorkbook()->GetIWorksheets()->SetActiveSheetIndex(dataSheetIdx);
// Получение книги и выбранного листа
intrusive_ptr<Aspose::Cells::IWorkbook> workbook = workbookDesigner->GetIWorkbook();
intrusive_ptr<Aspose::Cells::IWorksheet> work = workbook->GetIWorksheets()->GetObjectByIndex(dataSheetIdx);
// Масштабирование высоты строк и ширины столбцов в соответствии с пользовательским размером OLE
double height = OleHeight / 576.0f;
double width = OleWidth / 576.0f;
// Установка размера OLE в соответствии с выбранными строками и столбцами
SetOleAccordingToCustomHeightWidth(workbook, startRow, endRow, startCol, endCol, width, height, dataSheetIdx);
// Установка размера OLE в книге
workbook->GetIWorksheets()->SetOleSize(startRow, endRow, startCol, endCol);
workbook->GetIWorksheets()->GetObjectByIndex(0)->SetGridlinesVisible(false);
// Установка параметров изображения для получения изображения листа
intrusive_ptr<Aspose::Cells::Rendering::IImageOrPrintOptions> imageOrPrintOptions = Aspose::Cells::Factory::CreateIImageOrPrintOptions();
imageOrPrintOptions->SetImageFormat(Aspose::Cells::Systems::Drawing::Imaging::ImageFormat::GetBmp());
imageOrPrintOptions->SetOnePagePerSheet(onePagePerSheet);
intrusive_ptr<Aspose::Cells::Rendering::ISheetRender> render = Aspose::Cells::Factory::CreateISheetRender(workbookDesigner->GetIWorkbook()->GetIWorksheets()->GetObjectByIndex(dataSheetIdx), imageOrPrintOptions);
tempFileName.append(L".bmp");
render->ToImage(0, new String(tempFileName.c_str()));
System::String slidesTempFileName = System::String::FromWCS(tempFileName);
System::SharedPtr<System::Drawing::Image> image = ScaleImage(System::Drawing::Image::FromFile(slidesTempFileName), outputWidth, outputHeight);
System::String newTempFileName = slidesTempFileName.Replace(u".tmp", u".tmp1");
image->Save(newTempFileName, System::Drawing::Imaging::ImageFormat::get_Bmp());
// Добавление изображения в коллекцию изображений слайда
auto ppImage = presentation->get_Images()->AddImage(System::IO::File::ReadAllBytes(newTempFileName));
// Сохранение книги в поток и копирование в массив байтов
System::SharedPtr<System::IO::Stream> mstream = ToSlidesMemoryStream(workbook->SaveToStream());
System::ArrayPtr<uint8_t> chartOleData = System::MakeArray<uint8_t>(mstream->get_Length(), 0);
mstream->set_Position(0);
mstream->Read(chartOleData, 0, chartOleData->get_Length());
// Добавление OLE-объектной рамки
System::SharedPtr<OleEmbeddedDataInfo> dataInfo = System::MakeObject<OleEmbeddedDataInfo>(chartOleData, u"xls");
System::SharedPtr<IOleObjectFrame> oleObjectFrame = slide->get_Shapes()->AddOleObjectFrame(x, y, OleWidth, OleHeight, dataInfo);
// Установка изображения OLE-рамки и альтернативного текста
oleObjectFrame->get_SubstitutePictureFormat()->get_Picture()->set_Image(ppImage);
oleObjectFrame->set_AlternativeText(System::String(u"изображение") + ppImage);
}
System::SharedPtr<System::IO::MemoryStream> ToSlidesMemoryStream(intrusive_ptr<Aspose::Cells::Systems::IO::MemoryStream> inputStream)
{
System::ArrayPtr<uint8_t> outputBuffer = System::MakeArray<uint8_t>(inputStream->GetLength(), inputStream->GetBuffer()->ArrayPoint());
auto outputStream = System::MakeObject<System::IO::MemoryStream>(outputBuffer);
return outputStream;
}
System::SharedPtr<System::Drawing::Image> ScaleImage(System::SharedPtr<System::Drawing::Image> image, int32_t outputWidth, int32_t outputHeight)
{
if (outputWidth == 0 && outputHeight == 0)
{
outputWidth = image->get_Width();
outputHeight = image->get_Height();
}
System::SharedPtr<System::Drawing::Bitmap> outputImage = System::MakeObject<System::Drawing::Bitmap>(outputWidth, outputHeight, image->get_PixelFormat());
outputImage->SetResolution(image->get_HorizontalResolution(), image->get_VerticalResolution());
System::SharedPtr<System::Drawing::Graphics> graphics = System::Drawing::Graphics::FromImage(outputImage);
graphics->set_InterpolationMode(System::Drawing::Drawing2D::InterpolationMode::HighQualityBicubic);
System::Drawing::Rectangle srcDestRect(0, 0, outputWidth, outputHeight);
graphics->DrawImage(image, srcDestRect, srcDestRect, System::Drawing::GraphicsUnit::Pixel);
graphics->Dispose();
return outputImage;
}
Заключение
Существует два подхода для устранения проблемы изменения размера листа. Выбор подходящего подхода зависит от требований и конкретного случая использования. Оба подхода работают одинаково, независимо от того, создаются ли презентации из шаблона или с нуля. Кроме того, в решении нет ограничения на размер OLE-объектной рамки.
h4. {}Связанные разделы
{}
Создание и встраивание диаграммы Excel в качестве OLE-объекта в презентацию