python pandas ExcelWriter 将单元格格式化为文本时出现问题

python pandas ExcelWriter issue while formatting cells as text

我需要为我的 excel sheet 列着色,该列是从 pandas 数据框写入的。

这是我将给出的示例并解释我面临的问题。

df=pd.DataFrame(columns=['A2','B18'],data=[[10,123415209123456789],[12,1223152012345678088],[10,1234152091234566666],[12,1223152012345678777]],dtype='object')
print(df)

   A2                  B18
0  10   123415209123456789
1  12  1223152012345678088
2  10  1234152091234566666
3  12  1223152012345678777

print(df.info)

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 4 entries, 0 to 3
Data columns (total 2 columns):
#   Column  Non-Null Count  Dtype 
---  ------  --------------  ----- 
0   A2      4 non-null      object
1   B18     4 non-null      object
dtypes: object(2)
memory usage: 192.0+ bytes
None

我确实对颜色有一些复杂的格式要求,不仅要对齐数据,还要对齐 header。这就是我想到使用 excelwriter 而不是 pandas styler 的原因。

但是,我遇到了文本格式问题

#Create a Pandas Excel writer using XlsxWriter as the engine.
writer = pd.ExcelWriter(dataFolder + 'tmp_12_test126.xlsx', engine='xlsxwriter')

# Convert the dataframe to an XlsxWriter Excel object.
df.to_excel(writer,sheet_name='Sheet1',index=False)

# Get the xlsxwriter workbook and worksheet objects.
workbook  = writer.book

col_format=[{},{'bg_color': 'cyan', 'num_format': '@'}]

# Start iterating through the columns and the rows to apply the format
for col in range(df.shape[1]):
    for row in range(df.shape[0]):
        if len(col_format[col]) > 0 :
           worksheet.write(row+1,col,df.iloc[row,col],workbook.add_format(col_format[col]))

# Finally write the file
writer.save()

但是这会写入 B18 列,将其转换为科学记数法并导致丢失最后 4 位值。

任何人都可以帮助我做错什么吗? 我通读并发现 'num_format': '@' 是将单元格强制为文本格式所必需的。 但由于某种原因,它不起作用。

使用dtype=object 不会将数字转换为字符串。相反,它会尝试将每个值强制转换为最合适的 python 类型。如果你想要字符串而不是数字,你可以创建默认类型 dtype=str (强制所有列)或使用 astype():

为每列选择不同的类型
import pandas as pd

df1=pd.DataFrame(columns=['A2','B18'],
                 data=[[10,123415209123456789],
                       [12,1223152012345678088],
                       [10,1234152091234566666],
                       [12,1223152012345678777]],
                 dtype=object)

print('df1 types:')
[print(idx,type(val[0]),type(val[1])) for idx,val in df1.iterrows()]

df2=pd.DataFrame(columns=['A2','B18'],
                 data=[[10,123415209123456789],
                       [12,1223152012345678088],
                       [10,1234152091234566666],
                       [12,1223152012345678777]],
                 dtype=str)

print('df2 types:')
[print(idx,type(val[0]),type(val[1])) for idx,val in df2.iterrows()]

df3=pd.DataFrame(columns=['A2','B18'],
                 data=[[10,123415209123456789],
                       [12,1223152012345678088],
                       [10,1234152091234566666],
                       [12,1223152012345678777]]).astype({'A2': int, 'B18':str})

print('df3 types:')
[print(idx,type(val[0]),type(val[1])) for idx,val in df3.iterrows()]

输出:

df1 types:
0 <class 'int'> <class 'int'>
1 <class 'int'> <class 'int'>
2 <class 'int'> <class 'int'>
3 <class 'int'> <class 'int'>
df2 types:
0 <class 'str'> <class 'str'>
1 <class 'str'> <class 'str'>
2 <class 'str'> <class 'str'>
3 <class 'str'> <class 'str'>
df3 types:
0 <class 'int'> <class 'str'>
1 <class 'int'> <class 'str'>
2 <class 'int'> <class 'str'>
3 <class 'int'> <class 'str'>