0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

pythonでエクセル表をコピーしてパワポに張り付ける

Posted at

pythonでエクセルの表をコピーしてパワポに貼り付けるプログラムを作ってみました。
本当は文字と上下左右中央寄せもコピーしたかったけど疲れたでここで

openpyxlで特定の範囲で下記情報をコピー
・テキスト
・背景塗りつぶし色
・文字色
・太字情報
・セルのマージ情報
・不完全だけど表サイズ

●実行例、このぐらいコピーできれば個人的には満足
image.png

excel_to_pptxtable.py
import openpyxl
from openpyxl.styles import PatternFill, Font, Border
from openpyxl.utils import get_column_letter
import sys

def excel_get_cell_info(sheet, cellkey):
    '''
    cell情報を返す ( sheet , "B4" )
    #cell_obj = sheet["B2"] sheet["B2"].column_letter
    #cell_obj = sheet.cell(row=2, column=2)
    '''
    cell_obj = sheet[cellkey]
    # 塗りつぶし色
    fill_color = cell_obj.fill.start_color.index if cell_obj.fill else None
    # COLOR = "AARRGGBB" AA:不透明度00なら透明、RR:赤、GG:緑、BB:青
    if fill_color[0:2] == '00' or fill_color == None :
        font_color = '00FFFFFF'
        
    # 文字色
    font_color = cell_obj.font.color.index if cell_obj.font.color else None
    if font_color == 1 or font_color == None :
        font_color = '00000000'

    font_bold = cell_obj.font.bold
    
    # 枠線の有無
    borders = cell_obj.border
    border_info = {
        'top': bool(borders.top),
        'bottom': bool(borders.bottom),
        'left': bool(borders.left),
        'right': bool(borders.right),
    }

    # セルマージ情報
    merged_cells = sheet.merged_cells
    merged_range = [m.bounds for m in merged_cells if cellkey == str(m).split(":")[0]]
    if len(merged_range) > 0:
        #for m in merged_cells:
        #    print(str(m),cellkey == str(m).split(":")[0])
        ll = merged_range[0]
        #print("merged",ll[2] - ll[0],ll[3] - ll[1])

    # セルの値を取得
    value = cell_obj.value

    # 計算式の場合は計算結果を取得
    #if cell_obj.data_type == 'f':  # 'f' は計算式を示す
    #    formula_result = cell_obj.value  # 計算式の結果
    #    { 'type': 'formula', 'value': formula_result }
    
    # 文字列または数値の場合
    #if isinstance(value, (str, int, float)):
    #    { 'type': 'value', 'value': value }
    
    return {
        'fill_color': fill_color,
        'font_color': font_color,
        'font_bold' : font_bold,
        'value':value,
        'merged_range':merged_range,
        #'border_info': border_info,
    }
#enddef excel_get_cell_info

def tuple_to_a1(row, column):
    ## 使用例
    ##print(tuple_to_a1(3, 3))  # 出力: "C3"
    # 行番号を文字列に変換
    if row == 0 or column == 0 :
        print("excel row col >= 0",row,column)
        sys.exit()
    row_number = str(row)
    
    # 列番号を文字列に変換
    column_letter = ""
    while column > 0:
        column -= 1
        column_letter = chr(column % 26 + ord('A')) + column_letter
        column //= 26
    #
    return column_letter + row_number
#enddef

def excel_get_table_info(sheet, sr , sc , rowr , colr ):
    '''
    sheet:sheet
    sr:スタート行
    sc:スタート列
    rowr:読み込む行範囲
    colr:読み込む列範囲
    '''
    retcsv = []
    # 1行目、2行目、3行目と読んでいく
    for row_idy in range(sr,sr+rowr) :
        row = []
        # 1列目、2列目、3列目と
        for col_idx in range(sc,sc+colr) :
            cellkey = tuple_to_a1(row_idy,col_idx)
            #print("debug",cellkey,"row",row_idy,"col",col_idx)
            row.append( excel_get_cell_info(sheet, cellkey) )
        retcsv.append(row)
    #endfor
    
    # セルマージ情報print
    print("## cell marge start")
    for mr in sheet.merged_cells.ranges :
        print(mr)
        print(mr.bounds)
    #endfor
    print("## cell marge end")

    # セルの幅(文字数)と高さ(ポイント)で取得※文字数×7=ポイント
    pwidth = 0
    pheight = 0
    for rn in range( sr + rowr ) :
        pwidth += sheet.column_dimensions[get_column_letter(rn+1)].width
    for rn in range( sc + colr ) :
        pheight += sheet.row_dimensions[rn+1].height

    return retcsv , pwidth , pheight
#enddef

#############################
from pptx import Presentation
from pptx.util import Inches
from pptx.dml.color import RGBColor
from pptx.oxml.xmlchemy import OxmlElement

## https://stackoverflow.com/questions/42610829/python-pptx-changing-table-style-or-adding-borders-to-cells
def SubElement(parent, tagname, **kwargs):
        element = OxmlElement(tagname)
        element.attrib.update(kwargs)
        parent.append(element)
        return element
def _set_cell_border(cell, border_color="000000", border_width='12700'):
    linStyle = 'solid'
    tc = cell._tc
    tcPr = tc.get_or_add_tcPr()
    for lines in ['a:lnL','a:lnR','a:lnT','a:lnB']:
        ln = SubElement(tcPr, lines, w=border_width, cap='flat', cmpd='sng', algn='ctr')
        solidFill = SubElement(ln, 'a:solidFill')
        srgbClr = SubElement(solidFill, 'a:srgbClr', val=border_color)
        prstDash = SubElement(ln, 'a:prstDash', val=linStyle) ## 線のスタイル
        round_ = SubElement(ln, 'a:round')
        headEnd = SubElement(ln, 'a:headEnd', type='none', w='med', len='med')
        tailEnd = SubElement(ln, 'a:tailEnd', type='none', w='med', len='med')

'''
ppt_table_cell_font
pptxのテーブルのcellの文字色、太字の有無の設定
'''
def ppt_table_cell_font(cell,color=(0,0,0),bold=False):
            for paragraph in cell.text_frame.paragraphs: # 段落のループ
                for run in paragraph.runs: # 文字のループ
                    run.font.color.rgb = RGBColor(*color)  # 黒色に設定
                    run.font.bold = bold  # 太字を解除
#enddef

'''
ppt_table_reset
pptxのテーブルを一律設定
黒枠設定、塗りつぶし無し、文字色黒、太字無し
'''
def ppt_table_reset(table):
    num_rows = len(table.rows)
    num_cols = len(table.columns)
    for row in range(num_rows):
        for col in range(num_cols):
            cell = table.cell(row, col)
            # セル背景塗りつぶし
            cell.fill.solid()
            cell.fill.fore_color.rgb = RGBColor(255, 255, 255)  # 白色
            cell.fill.background() ##noFill
            # 線の設定
            _set_cell_border(table.cell(row, col))
            # 文字の設定
            ppt_table_cell_font(cell, (0,0,0),False)
#enddef

#############################
'''
argb_to_rgb('AARRGGBB')
AA は透明度
RGBを(129,44,00) みたいなのに変換
'''
def argb_to_rgb(argb_color):
    # 先頭の2文字を除去してRGBを取得
    alfa = int(argb_color[0:2],16)
    red = int(argb_color[2:4],16)
    green = int(argb_color[4:6],16)
    blue = int(argb_color[6:8],16)
    return (red, green, blue) , alfa
#enddef

'''
etcsv_to_ppt_table
エクセルから取得したtable情報をpptのテーブルで作成
'''
def etcsv_to_ppt_table( etcsv , slide ,pwidth,pheight) :
    # テーブルの作成
    rows, cols = len(etcsv),len(etcsv[0]), 
    left = Inches(1)
    top = Inches(1)
    width = Inches(pwidth*3/73) # エクセルのwidthは文字数なのでpointに変換するために2~7×
    height = Inches(pheight/73)
    table = slide.shapes.add_table(rows,cols,  left, top, width, height).table
    ppt_table_reset(table)

    #print("debug range",rows,cols)
    # 1行目、2行目、3行目と読んでいく
    for row in range(rows):
        for col in range(cols):
            ptablecell = table.cell(row,col,)
            etcell = etcsv[row][col]
            
            # value
            if etcell['value'] != None :
                ptablecell.text = etcell['value']

            #print("debug","r",row,"c",col,"value",etcell['value'])
            
            # y行x列をマージ
            merge_cell = etcell['merged_range']
            if len(merge_cell) > 0:
                merge_cell_range = merge_cell[0]
                mergeend_col = col + merge_cell_range[2]-merge_cell_range[0] # +1
                mergeend_row = row + merge_cell_range[3]-merge_cell_range[1] # +1
                #print("debug","r",row,"c",col,"merge","mr",mergeend_row,"mc",mergeend_col)
                ptablecell.merge(table.cell(mergeend_row,mergeend_col,))

            # セル背景塗りつぶし
            if etcell['fill_color'][0:2] != '00' :
                ptablecell.fill.solid()
                #ptablecell.fill.background() ##noFill
                fcolor , alfa = argb_to_rgb(etcell['fill_color'])
                ptablecell.fill.fore_color.rgb = RGBColor( *fcolor ) ## 塗りつぶし

            # 文字の設定
            fcolor , alfa = argb_to_rgb(etcell['font_color'])
            ppt_table_cell_font(ptablecell,fcolor,etcell['font_bold'])
#############


if __name__ == '__main__':
    # 使用例
    file_path = 'sss2.xlsx'  # Excelファイルのパス

    # Excelファイルを読み込む
    wb = openpyxl.load_workbook(file_path)
    print("## sheetname start")
    for sname in wb.sheetnames :
        print(sname)
    print("## sheetname end")

    # 指定した範囲をコピー
    # sheets,sr行,sc列,rowr行,colr列
    # B2:E10 , (2,2)-(5-9) , (2,2)->[4,8]
    excellinfo_csv ,pwidth ,pheight = excel_get_table_info(wb['22'],2,2,8,4)

    if False : # debug
        for row_idy , valy in enumerate(excellinfo_csv) :
            for col_idx , val in enumerate(valy) :
                print( row_idy , col_idx , val )

    # プレゼンテーションを作成
    prs = Presentation()
    # スライドを追加
    slide_layout = prs.slide_layouts[5]  # 空白のスライド
    slide = prs.slides.add_slide(slide_layout)

    # エクセルからコピーしてきたデータをスライドに張り付け
    etcsv_to_ppt_table(excellinfo_csv,slide,pwidth,pheight)
    # プレゼンテーションを保存
    prs.save('table_presentation.pptx')
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?