Saya diminta untuk membuat beberapa laporan Excel. Saat ini saya menggunakan pandas cukup banyak untuk data saya, jadi tentu saja saya ingin menggunakan metode pandas.ExcelWriter untuk menghasilkan laporan ini. Namun lebar kolom tetap menjadi masalah.
Kode yang saya miliki sejauh ini cukup sederhana. Katakanlah saya memiliki dataframe yang disebut 'df':
writer = pd.ExcelWriter(excel_file_path, engine='openpyxl')
df.to_excel(writer, sheet_name="Summary")
Saya melihat-lihat kode pandas, dan saya tidak benar-benar melihat opsi untuk mengatur lebar kolom. Apakah ada trik di luar sana di alam semesta untuk membuatnya sedemikian rupa sehingga kolom menyesuaikan secara otomatis dengan data? Atau apakah ada sesuatu yang dapat saya lakukan setelah fakta ke file xlsx untuk menyesuaikan lebar kolom?
(Saya menggunakan pustaka OpenPyXL, dan membuat file .xlsx - jika ada bedanya.)
Terima kasih.
to_excel
, mungkincol_style=dict
yang berisi elemen gaya header col (daripada defaultheader_style
yang tampaknya sulit dikodekan sekarangJawaban:
Terinspirasi oleh jawaban user6178746 , saya memiliki yang berikut:
# Given a dict of dataframes, for example: # dfs = {'gadgets': df_gadgets, 'widgets': df_widgets} writer = pd.ExcelWriter(filename, engine='xlsxwriter') for sheetname, df in dfs.items(): # loop through `dict` of dataframes df.to_excel(writer, sheet_name=sheetname) # send df to writer worksheet = writer.sheets[sheetname] # pull worksheet object for idx, col in enumerate(df): # loop through all columns series = df[col] max_len = max(( series.astype(str).map(len).max(), # len of largest item len(str(series.name)) # len of column name/header )) + 1 # adding a little extra space worksheet.set_column(idx, idx, max_len) # set column width writer.save()
sumber
worksheet.set_column(idx+nlevels, idx+nlevels, max_len)
. Jika tidak, panjangnya dihitung untuk kolom pertama frame, dan kemudian diterapkan ke kolom pertama di excel, yang mungkin merupakan indeks.enumerate(df)
seharusnyaenumerate(df.columns)
karena Anda mengulang setiap kolom dalamdf
.dict
sebenarnya iterasi atas kunci didict
(Anda tidak perlu mengatakannya secara manualdict.keys()
), melakukan iterasi dipd.DataFrame
atas kolom yang berulang. Anda tidak perlu mengulang secara manualdf.columns
.Saya memposting ini karena saya baru saja mengalami masalah yang sama dan menemukan bahwa dokumentasi resmi untuk Xlsxwriter dan panda masih memiliki fungsi ini terdaftar sebagai tidak didukung. Saya meretas solusi yang menyelesaikan masalah yang saya alami. Saya pada dasarnya hanya mengulang melalui setiap kolom dan menggunakan worksheet.set_column untuk mengatur lebar kolom == panjang maksimal dari isi kolom itu.
Namun, ada satu catatan penting. Solusi ini tidak sesuai dengan tajuk kolom, hanya nilai kolomnya. Itu harus menjadi perubahan yang mudah meskipun jika Anda perlu menyesuaikan header saja. Semoga ini bisa membantu seseorang :)
import pandas as pd import sqlalchemy as sa import urllib read_server = 'serverName' read_database = 'databaseName' read_params = urllib.quote_plus("DRIVER={SQL Server};SERVER="+read_server+";DATABASE="+read_database+";TRUSTED_CONNECTION=Yes") read_engine = sa.create_engine("mssql+pyodbc:///?odbc_connect=%s" % read_params) #Output some SQL Server data into a dataframe my_sql_query = """ SELECT * FROM dbo.my_table """ my_dataframe = pd.read_sql_query(my_sql_query,con=read_engine) #Set destination directory to save excel. xlsFilepath = r'H:\my_project' + "\\" + 'my_file_name.xlsx' writer = pd.ExcelWriter(xlsFilepath, engine='xlsxwriter') #Write excel to file using pandas to_excel my_dataframe.to_excel(writer, startrow = 1, sheet_name='Sheet1', index=False) #Indicate workbook and worksheet for formatting workbook = writer.book worksheet = writer.sheets['Sheet1'] #Iterate through each column and set the width == the max length in that column. A padding length of 2 is also added. for i, col in enumerate(my_dataframe.columns): # find length of column i column_len = my_dataframe[col].astype(str).str.len().max() # Setting the length if the column header is larger # than the max column value length column_len = max(column_len, len(col)) + 2 # set the column length worksheet.set_column(i, i, column_len) writer.save()
sumber
()
di dalam fungsi maks: `max (column_len (), len (col)) + 2`Mungkin tidak ada cara otomatis untuk melakukannya saat ini, tetapi saat Anda menggunakan openpyxl, baris berikut (diadaptasi dari jawaban lain oleh pengguna Bufke tentang cara melakukannya secara manual ) memungkinkan Anda untuk menentukan nilai yang waras (dalam lebar karakter):
writer.sheets['Summary'].column_dimensions['A'].width = 15
sumber
column_dimensions
atribut. Jika Anda ingin tetap menggunakan openpyxl, cukup tentukan saat membuat penulis menggunakanpd.ExcelWriter(excel_filename, engine='openpyxl')
Xlsxwriter
sebagai mesin untuk melihat bagaimana menentukan lebar kolom dengan mesin default hari ini.Ada paket bagus yang saya mulai gunakan baru-baru ini yang disebut StyleFrame.
itu mendapat DataFrame dan memungkinkan Anda untuk menatanya dengan sangat mudah ...
secara default, lebar kolom diatur secara otomatis.
sebagai contoh:
from StyleFrame import StyleFrame import pandas as pd df = pd.DataFrame({'aaaaaaaaaaa': [1, 2, 3], 'bbbbbbbbb': [1, 1, 1], 'ccccccccccc': [2, 3, 4]}) excel_writer = StyleFrame.ExcelWriter('example.xlsx') sf = StyleFrame(df) sf.to_excel(excel_writer=excel_writer, row_to_add_filters=0, columns_and_rows_to_freeze='B2') excel_writer.save()
Anda juga dapat mengubah lebar kolom:
sf.set_column_width(columns=['aaaaaaaaaaa', 'bbbbbbbbb'], width=35.3)
UPDATE 1
Dalam versi 1.4,
best_fit
argumen ditambahkan keStyleFrame.to_excel
. Lihat dokumentasinya .UPDATE 2
Berikut adalah contoh kode yang berfungsi untuk StyleFrame 3.xx
from styleframe import StyleFrame import pandas as pd columns = ['aaaaaaaaaaa', 'bbbbbbbbb', 'ccccccccccc', ] df = pd.DataFrame(data={ 'aaaaaaaaaaa': [1, 2, 3, ], 'bbbbbbbbb': [1, 1, 1, ], 'ccccccccccc': [2, 3, 4, ], }, columns=columns, ) excel_writer = StyleFrame.ExcelWriter('example.xlsx') sf = StyleFrame(df) sf.to_excel( excel_writer=excel_writer, best_fit=columns, columns_and_rows_to_freeze='B2', row_to_add_filters=0, ) excel_writer.save()
sumber
best_fit
parameter. Juga, ketika saya mencoba ini, saya mendapatkan hasil yang sangat buruk .index
parameter tetapi tidak ada dadu.sf.apply_headers_style(Styler(bold=False))
saya butuh waktu lama untuk mengetahuinya. Dan dalam pernyataan imporfrom StyleFrame import StyleFrame, Styler
,. inilah semua opsi selain dari huruf tebal: styleframe.readthedocs.io/en/2.0.5/…from styleframe import StyleFrame
sesuai dengan konvensi nama PEP8Dengan menggunakan pandas dan xlsxwriter Anda dapat melakukan tugas Anda, kode di bawah ini akan bekerja dengan sempurna di Python 3.x. Untuk detail lebih lanjut tentang bekerja dengan XlsxWriter dengan panda, tautan ini mungkin berguna https://xlsxwriter.readthedocs.io/working_with_pandas.html
import pandas as pd writer = pd.ExcelWriter(excel_file_path, engine='xlsxwriter') df.to_excel(writer, sheet_name="Summary") workbook = writer.book worksheet = writer.sheets["Summary"] #set the column width as per your requirement worksheet.set_column('A:A', 25) writer.save()
sumber
Sesuaikan semua panjang kolom secara dinamis
writer = pd.ExcelWriter('/path/to/output/file.xlsx') df.to_excel(writer, sheet_name='sheetName', index=False, na_rep='NaN') for column in df: column_length = max(df[column].astype(str).map(len).max(), len(column)) col_idx = df.columns.get_loc(column) writer.sheets['sheetName'].set_column(col_idx, col_idx, column_length)
Sesuaikan kolom secara manual menggunakan Nama Kolom
col_idx = df.columns.get_loc('columnName') writer.sheets['sheetName'].set_column(col_idx, col_idx, 15)
Sesuaikan kolom secara manual menggunakan Indeks Kolom
writer.sheets['sheetName'].set_column(col_idx, col_idx, 15)
Jika salah satu hal di atas gagal dengan
AttributeError: 'Worksheet' object has no attribute 'set_column'
pastikan untuk menginstal
xlsxwriter
:sumber
Saya menemukan bahwa lebih bermanfaat untuk menyesuaikan kolom dengan berdasarkan tajuk kolom daripada konten kolom.
Menggunakan
df.columns.values.tolist()
I menghasilkan daftar tajuk kolom dan menggunakan panjang tajuk ini untuk menentukan lebar kolom.Lihat kode lengkap di bawah ini:
import pandas as pd import xlsxwriter writer = pd.ExcelWriter(filename, engine='xlsxwriter') df.to_excel(writer, index=False, sheet_name=sheetname) workbook = writer.book # Access the workbook worksheet= writer.sheets[sheetname] # Access the Worksheet header_list = df.columns.values.tolist() # Generate list of headers for i in range(0, len(header_list)): worksheet.set_column(i, i, len(header_list[i])) # Set column widths based on len(header) writer.save() # Save the excel file
sumber
Di tempat kerja, saya selalu menulis kerangka data ke file excel. Jadi, alih-alih menulis kode yang sama berulang kali, saya telah membuat modulus. Sekarang saya hanya mengimpor dan menggunakannya untuk menulis dan memformat file excel. Namun ada satu sisi negatifnya, dibutuhkan waktu lama jika kerangka data ekstra besar. Jadi inilah kodenya:
def result_to_excel(output_name, dataframes_list, sheet_names_list, output_dir): out_path = os.path.join(output_dir, output_name) writerReport = pd.ExcelWriter(out_path, engine='xlsxwriter', datetime_format='yyyymmdd', date_format='yyyymmdd') workbook = writerReport.book # loop through the list of dataframes to save every dataframe into a new sheet in the excel file for i, dataframe in enumerate(dataframes_list): sheet_name = sheet_names_list[i] # choose the sheet name from sheet_names_list dataframe.to_excel(writerReport, sheet_name=sheet_name, index=False, startrow=0) # Add a header format. format = workbook.add_format({ 'bold': True, 'border': 1, 'fg_color': '#0000FF', 'font_color': 'white'}) # Write the column headers with the defined format. worksheet = writerReport.sheets[sheet_name] for col_num, col_name in enumerate(dataframe.columns.values): worksheet.write(0, col_num, col_name, format) worksheet.autofilter(0, 0, 0, len(dataframe.columns) - 1) worksheet.freeze_panes(1, 0) # loop through the columns in the dataframe to get the width of the column for j, col in enumerate(dataframe.columns): max_width = max([len(str(s)) for s in dataframe[col].values] + [len(col) + 2]) # define a max width to not get to wide column if max_width > 50: max_width = 50 worksheet.set_column(j, j, max_width) writerReport.save() return output_dir + output_name
sumber
Menggabungkan jawaban dan komentar lain dan juga mendukung multi-indeks:
def autosize_excel_columns(worksheet, df): autosize_excel_columns_df(worksheet, df.index.to_frame()) autosize_excel_columns_df(worksheet, df, offset=df.index.nlevels) def autosize_excel_columns_df(worksheet, df, offset=0): for idx, col in enumerate(df): series = df[col] max_len = max(( series.astype(str).map(len).max(), len(str(series.name)) )) + 1 worksheet.set_column(idx+offset, idx+offset, max_len) sheetname=... df.to_excel(writer, sheet_name=sheetname, freeze_panes=(df.columns.nlevels, df.index.nlevels)) worksheet = writer.sheets[sheetname] autosize_excel_columns(worksheet, df) writer.save()
sumber
import re import openpyxl .. for col in _ws.columns: max_lenght = 0 print(col[0]) col_name = re.findall('\w\d', str(col[0])) col_name = col_name[0] col_name = re.findall('\w', str(col_name))[0] print(col_name) for cell in col: try: if len(str(cell.value)) > max_lenght: max_lenght = len(cell.value) except: pass adjusted_width = (max_lenght+2) _ws.column_dimensions[col_name].width = adjusted_width
sumber
Solusi termudah adalah menentukan lebar kolom dalam metode set_column.
for worksheet in writer.sheets.values(): worksheet.set_column(0,last_column_value, required_width_constant)
sumber
def auto_width_columns(df, sheetname): workbook = writer.book worksheet= writer.sheets[sheetname] for i, col in enumerate(df.columns): column_len = max(df[col].astype(str).str.len().max(), len(col) + 2) worksheet.set_column(i, i, column_len)
sumber
Ya, ada sesuatu yang dapat Anda lakukan setelah fakta ke file xlsx untuk menyesuaikan lebar kolom. Gunakan xlwings untuk mengisi otomatis kolom. Ini solusi yang cukup sederhana, lihat enam baris terakhir dari kode contoh. Keuntungan dari prosedur ini adalah Anda tidak perlu khawatir tentang ukuran font, jenis font, atau hal lainnya. Persyaratan: Instalasi Excel.
import pandas as pd import xlwings as xw report_file = "test.xlsx" df1 = pd.DataFrame([ ('this is a long term1', 1, 1, 3), ('this is a long term2', 1, 2, 5), ('this is a long term3', 1, 1, 6), ('this is a long term2', 1, 1, 9), ], columns=['term', 'aaaa', 'bbbbbbb', "cccccccccccccccccccccccccccccccccccccccccccccc"]) writer = pd.ExcelWriter(report_file, engine="xlsxwriter") df1.to_excel(writer, sheet_name="Sheet1", index=False) workbook = writer.book worksheet1 = writer.sheets["Sheet1"] num_format = workbook.add_format({"num_format": '#,##0.00'}) worksheet1.set_column("B:D", cell_format=num_format) writer.save() # Autofit all columns with xlwings. app = xw.App(visible=False) wb = xw.Book(report_file) for ws in wb.sheets: ws.autofit(axis="columns") wb.save(report_file) app.quit()
sumber