在Python中动态生成XLSXWriter图表 - 不引用 [英] Dynamically produced XLSXWriter charts in python - not referencing

查看:229
本文介绍了在Python中动态生成XLSXWriter图表 - 不引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用我写的下面的类,尝试使用多个工作表动态创建一个单独的Excel文件,其中每个工作表中都有一个打印的数据框和一个列图。



与代码交互(见下文)应该在您启动工作簿的地方运行:

 code> test = Workbook('Test Workbook')

然后,您可以添加为许多图表如下:

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

然后你生成工作簿:

  test.produce()

输入数据帧有标题。第一列是文本类别,后续列(不同数字)是小数形式的数据,要作为百分比绘制。



问题:代码工作相当不错,似乎与图表分开生成所有的工作表,但有些图表显示为未引用,这意味着当我点击列图中的一个栏时,它不会突出显示源数据。一些使用代码生成的图表,DO适当地引用,所以我不知道问题在哪里,没有明显的趋势。

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

#循环通过df中的列,并将范围中的n转换为列表
(0,df_width ):
col_n = dataframe [col_names [n]]。tolist()

#检查列是否有数字,如果是 - >转换为浮动!
如果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 convert in]]
convert.insert(0,col_names [n])
col_n = convert
else:
col_n.insert(0 ,col_names [n])

col_as_lists.append(col_n)

#将每个列表打印到工作表中。
worksheet.write_column(self.letters [n] +'1',col_as_lists [n])

#以数字数字形式表示百分比
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)

工作表= self.workbook.add_worksheet(tab_name)
self.print_frame(工作表,数据框,df_width,start_data_index)

chart = self.workbook.add_chart({'type':'column'})
df_length =(len dataframe.index))

范围内的n(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。字母[n] +'$ 2:$'+ self.letters [n] +'$'+ str(df_length + 1),
'fill':{'color':'#FFB11E'},
'data_labels':{'value':True,'center':True}
})

chart.set_title({'name':tab_name})
图.set_x_axis({'major_gridlines':{'visible':False}})
chart.set_y_axis({'major_gridlines':{'visible':False},'max':.70})

workheet.insert_chart(self.letters [df_width + 2] +'2',图表)

返回

def is_number(self,s):
用于帮助检测和转换浮点数
从字符串到数字数据类型的函数。
try:
float(s)
return True
除了ValueError:
返回False


解决方案

您的示例调用:

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



<建议你有时在名字中有空格。当您尝试像

 'name':'='+ tab_name +'!$'+ self 。

$ b $

 $ b 

 'name':'= Df Title!$ A $ 1',

(当 tab_name 等于'Df标题' n 等于 0 )。



你还应该能够具有空格的表格引用,但用单引号括起来,如

 'name':='Df Title'!$ A $ 1,

所以一个更强大的代码方式是

 'name':='+ tab_name +'!$+ self.letters [n] +'$ 1',

我有点惊讶,图表会使用破碎的表格参考书,但我实际上没有测试图表我自己,只是简单的单元格公式涉及表名。


I'm using the below class I've written to try and dynamically create a single Excel file with several worksheets where there is a printed dataframe and a column chart in each worksheet.

Interacton with the code (seen below) should function where you initiate a workbook:

test = Workbook('Test Workbook')

And then, you can add as many charts as you want:

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

And then you produce the workbook:

test.produce()

Input dataframes have headers. First column is text categories, subsequent columns (of varying number) are data in the form of decimals, that are to be graphed as percents.

THE ISSUE: The code works fairly well, and seems to produce all of the worksheets separately with charts, BUT some of the charts appear as "not referenced", meaning that when I click on a bar in the column chart, it does not highlight the source data. Some of the charts produced with the code, DO reference appropriately, so I am not sure where the issue is, and there is not an obvious trend.

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

解决方案

Your example invocations:

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

suggest that you sometimes had spaces in the names. This results in broken references when you try things like

'name': '=' + tab_name +'!$' + self.letters[n] + '$1',

which would evaluate to

'name': '=Df Title!$A$1',

(when tab_name equals 'Df Title' and n equals 0), for example.

You should still be able to have sheet references with spaces, but enclosed in single-quotes, like

'name': "='Df Title'!$A$1",

so a more robust way to code would be

'name': "='" + tab_name +"'!$" + self.letters[n] + '$1',

I'm a little surprised that the charts would work at all with the broken sheet references, but I haven't actually tested charts myself, just plain cell formulas that involve sheet names.

这篇关于在Python中动态生成XLSXWriter图表 - 不引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆