
著者:涼子
出典:バンプデータ
少し前まで、同僚がリーダーと話すプロジェクトを持っていました。作業の一部は、エクセルシートの日次データに基づいており、日次レポートに分類され、形式に従って単語で書かれていました。
いいやつ!補うのに178日かかります。コピーして貼り付ける必要がある場合は、肝臓から血を吐き出しているのではないでしょうか(自分で解決できます!)
わかりました、ojbk、Pythonオフィス自動化を提供する時が来ました。

まず、データサンプルと出力ドキュメントの要件を見てみましょう(機密データは調和して処理されています):元のexcelファイルにはn個のサブテーブルがあり、各サブテーブルは1日のデータです。レコードはなく、レコード(部門の数)があります。 ≥1、各部門のレコード数≥1)2つの場合、2つの日報に分類する必要があります。1つはプレーンテキストの説明で、もう1つは表付きのドキュメントです。



袖をまくって呪う!
いいえ、コードを書き始めてください!
まず、サブテーブルを1つにまとめます。これは、毎日のデータ記録のルールを統一的に観察するのに便利であり、後の処理にも便利です。 xlrdライブラリを使用してテーブルを読み取り、ワークブック内のアクティブなテーブルの名前を取得してから、pandasライブラリを使用してサブテーブルをトラバースしてマージします。データフレーム形式のデータは、excelテーブルとの優れた互換性を備えています。
def merge_sheet(filepath): #同じヘッダーを持つ複数のサブテーブルを組み合わせる
wb = xlrd.open_workbook(filepath)
sheets = wb.sheet_names()
df_total = pd.DataFrame()for name in sheets:
df = pd.read_excel(filepath, sheet_name=name)
df_total = df_total.append(df)
df_total.to_excel("merge.xlsx", index=False)
出力する必要のある日報フォーマットに応じて、記録なしで日報を出力するには、[日付]欄と[レポート部門]欄を読むだけで、[レポート部門]が非日付期間としてリストされ、毎日出力されます。元のテーブルのデータを観察し、レコードが報告されていないデータを直接フィルタリングして、「なし」という名前のサブテーブルにドロップします。

ここでは、 .groupby()を使用して[Department for Reporting]列をグループ化し、[None]グループを選択することもできますが、注意すべき点が1つあります。Pythonは非常に強力ですが、すべてをPythonに任せる必要はありません。
インポートライブラリとモジュールは次のとおりです。
import pandas as pd
import xlrd
from docx import Document
from docx.shared import Pt
from docx.shared import Inches
from docx.oxml.ns import qn
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from docx.enum.section import WD_ORIENTATION
基本的なプロセスは非常に単純で、レコードを報告せずにデータを読み込み、日付ごとにワードドキュメントを出力します。
def wu_to_word(filepath):
df = pd.read_excel(filepath, sheet_name="番号")
date_list =list(df['日付'])for d in date_list:
filename = wordname+str(d)+").docx" #出力ワードファイル名
title ="("+str(d)[:4]+"."+str(d)[4:6]+"."+str(d)[6:8]+")" #サブタイトル日付XXXX.XX.XX
word =str(d)[:4]+"年"+str(d)[4:6]+"月"+str(d)[6:8]+"日" #開始、署名日XXXX年XX月XX日
wu_doc(title, word, filename)print(f"ファイル:{filename},{title},{word}保存しました")
各ドキュメントで使用されるのと同じコンテンツを最初に設定することもできます。
wordname = "XX会社のビジネスデータシート(日報" all_title = "XX会社のビジネスレポート"
テーブルを追加せずにワードコンテンツを生成するのは比較的簡単です。フォーマットの調整に注意してください。
def wu_doc(title,word,filename): #サブタイトルの日付、段落の先頭と署名の日付、およびファイル名を渡します
doc =Document() #ドキュメントオブジェクトを作成する
section = doc.sections[0] #ページノードを取得
section.orientation = WD_ORIENTATION.LANDSCAPE #ページの向きを水平に設定します
new_width, new_height = section.page_height, section.page_width #元の長さと幅を入れ替えて、垂直ページを水平に実現します
section.page_width = new_width
section.page_height = new_height
# 段落のグローバル設定
doc.styles['Normal'].font.name = u'ソンティ' #フォント
doc.styles['Normal']._element.rPr.rFonts.set(qn('w:eastAsia'), u'ソンティ') #中国のフォントはこの設定を追加する必要があります
doc.styles['Normal'].font.size =Pt(14) #フォントサイズ4は14に対応します
t1 = doc.add_paragraph() #段落を追加する
t1.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER #中央揃え
_ t1 = t1.add_run(all_title) #段落の内容を追加する(見出し)
_ t1.bold = True #大胆な
_ t1.font.size =Pt(22)
t2 = doc.add_paragraph() #別の段落を追加する
t2.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER #中央揃え
_ t2 = t2.add_run(title +"\n") #段落コンテンツの追加(サブタイトル)
_ t2.bold = True
doc.add_paragraph(word +"記録はありません。\n\n").paragraph_format.first_line_indent =Inches(0.35) #コンテンツを追加しながら段落を追加し、最初の行のインデントを設定します
doc.add_paragraph(word).paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT #署名日を右揃え
doc.save(dir+filename) #パスで+ファイル名保存
実施した!報道の記録がない日刊紙104冊を書いてください。ただ商売をしましょう。残りは勉強したくありません。

報告されたデータの処理は比較的複雑です。最初に元のデータを見てみましょう。

たとえば、X年X月X日、N部門がデータを入力しました。ドキュメントのサンプルによると、段落の説明部分は次の形式に編成する必要があります。
部門A:「提出内容1」Xレコード;「提出内容2」Yレコード;部門B:...;部門C:...;
また、添付テーブルの部分は次の形式で整理する必要があります。各行に必要なデータのリストを整理して、行ごとにテーブルに書き込むことができます。
| レベル1インデックス | レベル2インデックス | レベル3インデックス | レベル4インデックス | 部門別の提出 | 備考 |
|---|---|---|---|---|---|
| lalala | hahaha | balabala | 空の場合は、上司に進みます | 部門A:コンテンツを送信します1 | レコードはありますが、アップロードされておらず、報告されていません。システムがクラッシュしました |
| aaa | bbb | ccc | ddd | 部門A:提出2 | アップロードされた、良いレポート |
| ... | ... | ... | ... | 部門B:コンテンツを送信1 | ... |
基本的なプロセスは似ています。メーターを読んだ後、最初に日付ごとにグループ化し、各グループには1日に1つ以上の部門データが含まれ、特定の日の添付に必要なフォームを生成し、段落の説明を整理し、最後に日付ごとに毎日の単語を出力します資料。
def what_to_word(filepath):
df = pd.read_excel(filepath, sheet_name="持ってる")
df.fillna('', inplace=True) #nanをnull文字に置き換えます
dates =[] #日付リスト
df_total =[] #日付によって保存されたすべてのdf
list_total =[] #各ワードに必要なテーブルデータのコレクション
for d in df.groupby('日付'):
dates.append(d[0])
df_total.append(d[1])for index,date inenumerate(dates):
list_oneday =[] #特定の単語に必要なテーブルデータ
for row inrange(len(df_total[index])):
list_row =get_table_data(df_total, index, row) #1行のデータ
list_oneday.append(list_row)
list_total.append(list_oneday)for index, date inenumerate(dates):
filename = wordname+str(date)+").docx" #出力ワードファイル名
title ="("+str(date)[:4]+"."+str(date)[4:6]+"."+str(date)[6:8]+")" #サブタイトル日付XXXX.XX.XX
word =str(date)[:4]+"年"+str(date)[4:6]+"月"+str(date)[6:8]+"日" #開始、署名日XXXX年XX月XX日
sentence =get_sentence(df_total, index) #その日の説明
what_doc(title, word, sentence, list_total[index], filename) #必要な内容を渡してから文書を出力する
print(f"ファイル:{filename}保存しました")
テーブルの整理、段落の整理、ドキュメントの出力の方法を見てみましょう。
エクセルテーブルのデータ行を取得し(説明: df_total [df_index]はデータフレームであり、その valuesは2次元のnumpy配列です)、すべてのレベルのインジケーター、送信ステータス、および各部門によるコメントを分類します。リストを返します。
def get_table_data(df_total, df_index, table_row):
list1 = df_total[df_index].values[table_row] #エクセルテーブルの行
list2 = list1[3:7] #1つから4つの指標
for i inrange(len(list2)): #現在のインジケーターが空の場合、上位のインジケーターが使用されます
if list2[i]=='空気' and i !=0:
list2[i]= list2[i -1]
content = list1[2]+":\n"+ list1[-4] #コンテンツを送信する
if'番号'in list1[-2]: #備考
remark ='一部のレコードがアップロードされていません。'+str(list1[-1])else:
remark ='アップロード'
list3 = list2.tolist() #numpy配列からリストリストまで、テーブルデータを単語で入力する必要があります
list3.append(str(content))
list3.append(str(remark))return list3
その日のデータの[報告部門]の列にある一意の値を数えると、Nの部門がデータを入力していることがわかります。部門をグループ化し、関連情報を取得し、「[(報告する内容、記録数、報告するかどうか、備考)]」の形式にまとめ、「N部門がデータを提出しました:部門X:」のように整理します。コンテンツXXX「Xレコード; ...」の説明文字列を送信します。
def get_sentence(df_total, df_index):
df_oneday = df_total[df_index]
num = df_oneday['報告部門'].nunique() #部門数
group =[] #部署名
detail =[] #要素がタプル形式である特定の部門のデータを組み合わせる(,,,)
info ='' #報告状況の説明
for item in df_oneday.groupby('報告部門'):
group.append(item[0])
detail.append(list(zip(list(item[1]['コンテンツを送信する']),list(item[1]['記録']),list(item[1]['報告するかどうか']),list(item[1]['備考']))))for index, g inenumerate(group): #各部門の報告状況を整理する
mes =str(g)+':' #部門開始
for i inrange(len(detail[index])):
_ mes = detail[index][i]ifint(_mes[1])>0:
mes = mes + f'“{_mes[0]}”{_mes[1]}記録;'
info = info + mes
info = info[:-1]+"。" #最後のセミコロンをピリオドに置き換えます
sentence = f"持ってる{num}各部門はデータを提出しました:{info}"return sentence
(忍耐警告!)単語のテキストと表のスタイルを調整する操作は面倒であり、段階的に設定する必要があります。プリセットヘッダーは次のとおりです。
table_title = ['第1レベルのインジケーター'、 '第2レベルのインジケーター'、 '第3レベルのインジケーター'、 '第4レベルのインジケーター'、 '各部門の提出状況'、 '備考']
その他の詳細については、コードコメントを参照してください。
def what_doc(title, word, sentence, table, filename): #着信サブタイトル日付、開始/署名日、段落、テーブルデータ、ファイル名
doc =Document()
section = doc.sections[0]
new_width, new_height = section.page_height, section.page_width
section.orientation = WD_ORIENTATION.LANDSCAPE
section.page_width = new_width
section.page_height = new_height
# 段落のグローバル設定
doc.styles['Normal'].font.name = u'ソンティ' #フォント
doc.styles['Normal']._element.rPr.rFonts.set(qn('w:eastAsia'), u'ソンティ') #中国のフォントはこの設定を追加する必要があります
doc.styles['Normal'].font.size =Pt(14) #フォントサイズ4は14に対応します
t1 = doc.add_paragraph() #見出し
t1.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER #中央揃え
_ t1 = t1.add_run(all_title)
_ t1.bold = True
_ t1.font.size =Pt(22)
t2 = doc.add_paragraph() #字幕
t2.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER #中央揃え
_ t2 = t2.add_run(title +"\n")
_ t2.bold = True
doc.add_paragraph(word + sentence +"\n\n").paragraph_format.first_line_indent =Inches(0.35) #最初の行のインデント
doc.add_paragraph(word).paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT #右揃え
doc.add_paragraph("各部門の具体的な報告状況については、添付資料を参照してください。")
doc.add_page_break() #ページネーション---------------------------------------------------------------
fujian = doc.add_paragraph().add_run("\nアクセサリ")
fujian.bold = True
fujian.font.size =Pt(16)
t3 = doc.add_paragraph() #添付ファイルの見出し
t3.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER #中央揃え
_ t3 = t3.add_run("XX社の事業データシート")
_ t3.bold = True
_ t3.font.size =Pt(22)
rows =len(table)+1
word_table = doc.add_table(rows=rows, cols=6, style='Table Grid') #行と6列のテーブルを作成します
word_table.autofit=True #境界線を追加
table =[table_title]+ table #固定ヘッダー+テーブルデータ
for row inrange(rows): #フォームを書く
cells = word_table.rows[row].cells
for col inrange(6):
cells[col].text =str(table[row][col])for i inrange(len(word_table.rows)): #ランクをトラバースし、スタイルを1つずつ変更します
for j inrange(len(word_table.columns)):for par in word_table.cell(i, j).paragraphs: #フォントサイズを変更する
for run in par.runs:
run.font.size =Pt(10.5)for par in word_table.cell(0, j).paragraphs: #最初の行を太字にする
for run in par.runs:
run.bold = True
doc.save(dir+filename)
実施した!記録のある74の日刊紙も書かれており、合計178部です。

作戦は熾烈で、ようやく日報がバッチで生成され、ランチにチキンレッグを追加する時が来ました...

記事のソースコードとデータに興味がある場合は、コンピューターのWebページで以下のリンクを開いてダウンロードできます。
https://alltodata.cowtransfer.com/s/9c8f675d2f7544
Recommended Posts