在Python中dynamic生成XLSXWriter图表 – 不参考

我正在使用下面的类,我写了试图dynamic创build一个Excel文件,其中有几个工作表,每个工作表中有一个打印的数据框和一个柱状图。

Interacton与代码(见下面)应该在你启动工作簿的地方起作用:

test = Workbook('Test Workbook') 

然后,您可以添加尽可能多的图表,只要你想:

 test.add_chart(df, 'Df Title', 1) test.add_chart(df2, 'Df2 Title', 1) 

然后你制作工作簿:

 test.produce() 

input数据框有标题。 第一列是文本类别,随后的列(不同数目)是以小数forms的数据,这些数据被绘制为百分比。

问题:代码工作得很好,似乎用图表分别生成了所有的工作表,但有些图表显示为“未引用”,这意味着当我点击柱状图中的一个条时,它不会突出显示源数据。 一些用代码编写的图表,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 

您的示例调用:

 test.add_chart(df, 'Df Title', 1) test.add_chart(df2, 'Df2 Title', 1) 

build议你有时在名字中有空格。 当您尝试类似的情况时,这会导致引用错误

 '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', 

我有点惊讶的是,图表可以在破碎的工作表参考下工作,但是我实际上并没有真正地testing过图表,只是涉及表名的普通单元格公式。

@John Y是正确的,您没有在图表范围引用中正确引用工作表名称。

您可以通过使用图表列表语法而不是string语法来避免此问题以及从数字到单元格引用的手动转换:

 chart.add_series({ 'name': ['Sheet1', 0, col], 'categories': ['Sheet1', 1, 0, max_row, 0], 'values': ['Sheet1', 1, col, max_row, col], }) 

这段代码来自XlsxWriter文档中的这个例子 。

这也适用于您的代码中的其他几个地方。 作为XlsxWriter的一般规则,您可以在任何使用A1语法的地方使用row-column语法: 使用单元格表示法 。