我使用下面的I类编写来尝试动态创建一个包含多个工作表的Excel文件,其中每个工作表中都有打印的数据框和柱形图。
使用代码(如下所示)的Interacton应该在您启动工作簿的位置运行:
test = Workbook('Test Workbook')
然后,您可以根据需要添加任意数量的图表:
test.add_chart(df, 'Df Title', 1)
test.add_chart(df2, 'Df2 Title', 1)
然后你制作了工作簿:
test.produce()
输入数据框有标题。第一列是文本类别,后续列(具有不同数量)是小数形式的数据,将以百分比形式绘制。
问题:代码工作得相当好,似乎用图表分别生成所有工作表,但有些图表显示为"未引用",这意味着当我点击一个栏时在柱形图中,它不会突出显示源数据。使用代码生成的一些图表,DO适当引用,所以我不确定问题出在哪里,并且没有明显的趋势。
import xlsxwriter
import pandas as pd
class Workbook:
def __init__(self, workbook_name):
self.workbook_name = workbook_name
self.workbook = xlsxwriter.Workbook(str(self.workbook_name) + '.xlsx')
self.letters = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P']
def produce(self):
self.workbook.close()
print 'Created ' + str(self.workbook_name) + '.xlsx'
def print_frame(self, worksheet, dataframe, df_width, start_data_index):
col_as_lists = []
col_names = list(dataframe.columns.values)
# loops through columns in df and converts to list
for n in range(0, df_width):
col_n = dataframe[col_names[n]].tolist()
# checks to see if column has numbers, if so -> convert to float!
if n < start_data_index:
col_n.insert(0, col_names[n])
elif self.is_number(col_n[0]):
convert = col_n[0:]
convert = [float(x) for x in convert]
convert.insert(0, col_names[n])
col_n = convert
else:
col_n.insert(0, col_names[n])
col_as_lists.append(col_n)
# Prints each list into the worksheet.
worksheet.write_column(self.letters[n] + '1', col_as_lists[n])
#Formats numerical data as percentage
percentformat = self.workbook.add_format({'num_format': '0%'})
worksheet.set_column(self.letters[start_data_index] + ':' + self.letters[df_width], None, percentformat)
def add_chart(self, dataframe, tab_name, start_data_index):
df_width = len(dataframe.columns)
worksheet = self.workbook.add_worksheet(tab_name)
self.print_frame(worksheet, dataframe, df_width, start_data_index)
chart = self.workbook.add_chart({'type': 'column'})
df_length = (len(dataframe.index))
for n in range(start_data_index, df_width):
chart.add_series({
'name': '=' + tab_name +'!$' + self.letters[n] + '$1',
'categories': '=' + tab_name +'!$' + self.letters[start_data_index - 1] + '$2:$'+ self.letters[start_data_index - 1] + '$' + str(df_length + 1),
'values': '=' + tab_name +'!$' + self.letters[n] + '$2:$'+ self.letters[n] + '$' + str(df_length + 1),
'fill': {'color': '#FFB11E'},
'data_labels': {'value': True, 'center': True}
})
chart.set_title({'name': tab_name})
chart.set_x_axis({'major_gridlines': {'visible': False}})
chart.set_y_axis({'major_gridlines': {'visible': False}, 'max': .70})
worksheet.insert_chart(self.letters[df_width + 2] + '2', chart)
return
def is_number(self, s):
""" Function used to help with detecting and converting floats
from string to number data types."""
try:
float(s)
return True
except ValueError:
return False
答案 0 :(得分:3)
您的示例调用:
test.add_chart(df, 'Df Title', 1)
test.add_chart(df2, 'Df2 Title', 1)
建议你有时在名字中有空格。当您尝试
之类的操作时,这会导致参考文献被破坏'name': '=' + tab_name +'!$' + self.letters[n] + '$1',
将评估为
'name': '=Df Title!$A$1',
例如,(当tab_name
等于'Df Title'
且n
等于0
时)。
您仍然可以使用空格的工作表引用,但用单引号括起来,例如
'name': "='Df Title'!$A$1",
所以更强大的代码方式是
'name': "='" + tab_name +"'!$" + self.letters[n] + '$1',
我有点惊讶的是,图表对于破损的纸张参考完全有用,但我实际上并没有自己测试图表,只是涉及图纸名称的普通单元格公式。
答案 1 :(得分:3)
@John Y是正确的,您没有在图表范围引用中正确引用工作表名称。
您可以使用图表列表语法而不是字符串语法来避免此问题以及从数字到单元格引用的手动转换:
chart.add_series({
'name': ['Sheet1', 0, col],
'categories': ['Sheet1', 1, 0, max_row, 0],
'values': ['Sheet1', 1, col, max_row, col],
})
该代码段来自this example in the XlsxWriter docs。
这也适用于代码中的其他几个地方。作为XlsxWriter中的一般规则,您可以使用row-column
语法(几乎)使用A1
语法:Working with Cell Notation。