ワークシートリサイズの実装ソリューション
背景
記事 OLE の管理 では、Aspose.Slides for Python via .NET を使用して PowerPoint プレゼンテーションに OLE フレームを追加する方法を説明しました。オブジェクト プレビューの問題 に対処するため、選択したワークシート領域の画像を OLE オブジェクトフレームに割り当てました。出力されたプレゼンテーションで、ワークシート画像を表示する OLE オブジェクトフレームをダブルクリックすると Excel ブックがアクティブになります。エンドユーザーは実際の Excel ブックを自由に編集でき、編集後に Excel ブックの外側をクリックするとスライドに戻ります。このとき OLE オブジェクトフレームのサイズが変わります。リサイズ率は OLE オブジェクトフレームのサイズと埋め込まれた Excel ブックのサイズに依存します。
リサイズの原因
Excel ブックは独自のウィンドウサイズを持っており、最初のアクティベーション時に元のサイズを保持しようとします。一方、OLE オブジェクトフレームにも独自のサイズがあります。Microsoft によると、Excel ブックがアクティブになると、Excel と PowerPoint がサイズ交渉を行い、埋め込みプロセスの一部として正しい比例を保つように調整します。リサイズは Excel ウィンドウサイズと OLE オブジェクトフレームのサイズ・位置の差異に基づいて発生します。
作業ソリューション
リサイズ効果を回避するための 2 つの解決策があります。
- PowerPoint プレゼンテーション内の OLE フレームのサイズを、OLE フレーム内で希望する行数と列数の高さと幅に合わせてスケーリングする。
- OLE フレームのサイズを固定したまま、対象の行と列のサイズをスケーリングして、選択した OLE フレームサイズに収める。
OLE フレーム サイズのスケーリング
このアプローチでは、埋め込まれた Excel ブックの OLE フレームサイズを、ワークシート内の対象行と列の累積サイズに合わせて設定する方法を学びます。
テンプレート Excel シートがあり、それを OLE フレームとしてプレゼンテーションに追加したいとします。このシナリオでは、まずブック内の対象行の高さと対象列の幅の合計から OLE オブジェクトフレームのサイズを計算します。その後、計算した値で OLE フレームのサイズを設定します。PowerPoint の OLE フレームで赤い「EMBEDDED OLE OBJECT」メッセージを回避するため、ブック内の対象行と列の必要部分を画像として取得し、OLE フレームの画像として設定します。
def create_ole_image(cell_range, image_resolution):
page_setup = cell_range.worksheet.page_setup
page_setup.print_area = cell_range.address
page_setup.left_margin = 0.0
page_setup.right_margin = 0.0
page_setup.top_margin = 0.0
page_setup.bottom_margin = 0.0
page_setup.clear_header_footer()
image_options = cells.rendering.ImageOrPrintOptions()
image_options.image_type = cells.drawing.ImageType.PNG
image_options.vertical_resolution = image_resolution
image_options.horizontal_resolution = image_resolution
image_options.one_page_per_sheet = True
image_options.only_area = True
sheet_render = cells.rendering.SheetRender(cell_range.worksheet, image_options)
image_data = io.BytesIO()
sheet_render.to_image(0, image_data)
image_data.seek(0)
return image_data
start_row, row_count = 0, 10
start_column, column_count = 0, 13
worksheet_index = 0
image_resolution = 96
with cells.Workbook("sample.xlsx") as workbook:
worksheet = workbook.worksheets[worksheet_index]
# PowerPointでワークブック ファイルをOLEオブジェクトとして使用する場合の表示サイズを設定します。
last_row = start_row + row_count - 1
last_column = start_column + column_count - 1
workbook.worksheets.set_ole_size(start_row, last_row, start_column, last_column)
cell_range = worksheet.cells.create_range(start_row, start_column, row_count, column_count)
image_stream = create_ole_image(cell_range, image_resolution)
# OLE画像の幅と高さ(ポイント単位)を取得します。
with slides.Images.from_stream(image_stream) as image:
image_width = image.width * 72 / image_resolution
image_height = image.height * 72 / image_resolution
# 変更したワークブックを使用する必要があります。
with io.BytesIO() as ole_stream:
workbook.save(ole_stream, cells.SaveFormat.XLSX)
with slides.Presentation() as presentation:
slide = presentation.slides[0]
# OLE画像をプレゼンテーションのリソースに追加します。
image_stream.seek(0)
ole_image = presentation.images.add_image(image_stream)
# OLEオブジェクトフレームを作成します。
data_info = slides.dom.ole.OleEmbeddedDataInfo(ole_stream.getvalue(), "xlsx")
ole_frame = slide.shapes.add_ole_object_frame(10, 10, image_width, image_height, data_info)
ole_frame.substitute_picture_format.picture.image = ole_image
ole_frame.is_object_icon = False
presentation.save("output.pptx", slides.export.SaveFormat.PPTX)
セル範囲サイズのスケーリング
このアプローチでは、対象行の高さと対象列の幅をカスタム OLE フレームサイズに合わせてスケーリングする方法を学びます。
テンプレート Excel シートがあり、それを OLE フレームとしてプレゼンテーションに追加したいとします。このシナリオでは、OLE フレームのサイズを設定し、フレーム領域に参加する行と列のサイズをスケーリングします。その後、変更を適用するためにブックをストリームに保存し、バイト配列に変換して OLE フレームに追加します。PowerPoint の OLE フレームで赤い「EMBEDDED OLE OBJECT」メッセージを回避するため、ブック内の対象行と列の必要部分を画像として取得し、OLE フレームの画像として設定します。
# <param name="width">セル範囲の期待幅(ポイント単位)。</param>
# <param name="height">セル範囲の期待高さ(ポイント単位)。</param>
def scale_cell_range(cell_range, width, height):
range_width = cell_range.width
range_height = cell_range.height
for i in range(cell_range.column_count):
column_index = cell_range.first_column + i
column_width = cell_range.worksheet.cells.get_column_width(column_index, False, cells.CellsUnitType.POINT)
new_column_width = column_width * width / range_width
width_in_inches = new_column_width / 72
cell_range.worksheet.cells.set_column_width_inch(column_index, width_in_inches)
for i in range(cell_range.row_count):
row_index = cell_range.first_row + i
row_height = cell_range.worksheet.cells.get_row_height(row_index, False, cells.CellsUnitType.POINT)
new_row_height = row_height * height / range_height
height_in_inches = new_row_height / 72
cell_range.worksheet.cells.set_row_height_inch(row_index, height_in_inches)
def create_ole_image(cell_range, image_resolution):
page_setup = cell_range.worksheet.page_setup
page_setup.print_area = cell_range.address
page_setup.left_margin = 0.0
page_setup.right_margin = 0.0
page_setup.top_margin = 0.0
page_setup.bottom_margin = 0.0
page_setup.clear_header_footer()
image_options = cells.rendering.ImageOrPrintOptions()
image_options.image_type = cells.drawing.ImageType.PNG
image_options.vertical_resolution = image_resolution
image_options.horizontal_resolution = image_resolution
image_options.one_page_per_sheet = True
image_options.only_area = True
sheet_render = cells.rendering.SheetRender(cell_range.worksheet, image_options)
image_data = io.BytesIO()
sheet_render.to_image(0, image_data)
image_data.seek(0)
return image_data
start_row, row_count = 0, 10
start_column, column_count = 0, 13
worksheet_index = 0
image_resolution = 96
frame_width, frame_height = 400.0, 100.0
with cells.Workbook("sample.xlsx") as workbook:
worksheet = workbook.worksheets[worksheet_index]
# PowerPointでワークブック ファイルをOLEオブジェクトとして使用する際の表示サイズを設定します。
last_row = start_row + row_count - 1
last_column = start_column + column_count - 1
workbook.worksheets.set_ole_size(start_row, last_row, start_column, last_column)
# セル範囲をフレームサイズに合わせてスケーリングします。
cell_range = worksheet.cells.create_range(start_row, start_column, row_count, column_count)
scale_cell_range(cell_range, frame_width, frame_height)
image_stream = create_ole_image(cell_range, image_resolution)
# 変更したワークブックを使用する必要があります。
with io.BytesIO() as ole_stream:
workbook.save(ole_stream, cells.SaveFormat.XLSX)
with slides.Presentation() as presentation:
slide = presentation.slides[0]
# OLE画像をプレゼンテーションのリソースに追加します。
ole_image = presentation.images.add_image(image_stream)
# OLEオブジェクトフレームを作成します。
data_info = slides.dom.ole.OleEmbeddedDataInfo(ole_stream.getvalue(), "xlsx")
ole_frame = slide.shapes.add_ole_object_frame(10, 10, frame_width, frame_height, data_info)
ole_frame.substitute_picture_format.picture.image = ole_image
ole_frame.is_object_icon = False
presentation.save("output.pptx", slides.export.SaveFormat.PPTX)