首页 > 编程问答 >如何从Python中的“openpyxl”饼图中删除“Series1”标签?

如何从Python中的“openpyxl”饼图中删除“Series1”标签?

时间:2024-07-27 10:12:31浏览次数:5  
标签:python charts openpyxl excel-charts

我正在使用 openpyxl 创建一个包含饼图的 Excel 文件。但是,我似乎无法从图表中删除默认的“Series1”标签。为了更好的上下文,我已经包含了整个 export_to_excel 函数,但问题具体在于我创建饼图的分析表。

def export_to_excel(self):
    start_date = self.fromDate.date().toString('yyyy-MM-dd')
    end_date = self.toDate.date().toString('yyyy-MM-dd')
    start_time = self.fromTime.time().toString('HH:mm:ss')
    end_time = self.toTime.time().toString('HH:mm:ss')

    start_datetime = f"{start_date} {start_time}"
    end_datetime = f"{end_date} {end_time}"

    account_name = self.accountDropdown.currentText()
    search_term = self.itemName.text()
    search_amount = self.amount.text()

    query = '''
        SELECT expenses.id, expenses.item, expenses.amount, expenses.date, expenses.time, expenses.note, accounts.name, expenses.account_id 
        FROM expenses 
        JOIN accounts ON expenses.account_id = accounts.id
        WHERE datetime(expenses.date || ' ' || expenses.time) BETWEEN ? AND ? AND expenses.item LIKE ?
        ORDER BY expenses.date
    '''
    params = (start_datetime, end_datetime, f'%{search_term}%')

    self.c.execute(query, params)
    results = self.c.fetchall()
    thin_border = Border(
        left=Side(style='thin'),
        right=Side(style='thin'),
        top=Side(style='thin'),
        bottom=Side(style='thin')
    )

    if results:
        workbook = openpyxl.Workbook()
        sheet = workbook.active
        sheet.title = "Expenses"

        sheet.freeze_panes = "A3"
        sheet.page_setup.fitToWidth = 1
        sheet.page_setup.fitToHeight = False
        sheet.page_setup.paperSize = sheet.PAPERSIZE_A4

        # Date range row
        date_range = f"Expense Report: {start_date} to {end_date}"
        sheet.append([date_range])
        sheet.merge_cells(start_row=1, start_column=1, end_row=1, end_column=7)

        bold_underline_font = Font(bold=True, underline="single")
        date_range_cell = sheet.cell(row=1, column=1)
        date_range_cell.font = bold_underline_font
        date_range_cell.alignment = Alignment(horizontal='center', vertical='center')

        headers = ["Sr No.", "Amount", "Item", "Date", "Time", "Note", "Account Name"]
        sheet.append(headers)

        header_font = Font(bold=True)
        center_alignment = Alignment(horizontal='center')
        bold_center_alignment = Alignment(horizontal='center', vertical='center', wrap_text=True)

        for cell in sheet[2]:
            cell.font = header_font
            cell.alignment = bold_center_alignment if cell.value != "Note" else center_alignment
            cell.border = thin_border
        
        red_fill = PatternFill(start_color="FFCCCC", end_color="FFCCCC", fill_type="solid")
        bold_font = Font(bold=True)

        total_amount = 0
        item_amounts = {}

        for sr_no, row in enumerate(results, start=1):
            # Convert date to dd-MM-yyyy format
            date = QtCore.QDate.fromString(row[3], 'yyyy-MM-dd').toString('dd-MM-yyyy')
            row_data = [sr_no, row[2], row[1], date, row[4], row[5], row[6]]
            sheet.append(row_data)
            for col_num, value in enumerate(row_data, start=1):
                cell = sheet.cell(row=sheet.max_row, column=col_num)
                if col_num == 2 and isinstance(value, float) and value >= 3000:
                    cell.fill = red_fill
                    cell.font = bold_font
                if col_num != 6:
                    cell.alignment = center_alignment
                cell.border = thin_border

                if col_num == 4:
                    try:
                        total_amount += float(value)
                    except ValueError:
                        pass
            item = row[1]
            amount = row[2]
            total_amount += amount
            if item in item_amounts:
                item_amounts[item] += amount
            else:
                item_amounts[item] = amount

        total_row = sheet.max_row + 1
        sheet.cell(row=total_row, column=1, value="Total Amount")
        total_amount_cell = sheet.cell(row=total_row, column=2, value=total_amount)

        for column_cells in sheet.iter_cols(min_row=2, max_row=sheet.max_row):
            length = max(len(str(cell.value)) for cell in column_cells if not isinstance(cell, openpyxl.cell.MergedCell))
            sheet.column_dimensions[column_cells[0].column_letter].width = max(length, 10)

        # Create a new sheet for analytics
        analytics_sheet = workbook.create_sheet(title="Analytics")
        analytics_sheet.page_setup.orientation = analytics_sheet.ORIENTATION_LANDSCAPE

        # Add heading for the top 10 expenses
        heading = analytics_sheet.cell(row=1, column=1, value="Top 10 Expenses")
        heading.font = Font(bold=True, size=16)
        heading.alignment = Alignment(horizontal='center', vertical='center')
        analytics_sheet.merge_cells(start_row=1, start_column=1, end_row=1, end_column=8)

        # Create pie chart data for top 10 highest spent expenses
        # <-------- Pie chart Module Starts from here ----------->
        if item_amounts:
            sorted_items = sorted(item_amounts.items(), key=lambda x: x[1], reverse=True)
            top_items = sorted_items[:10]
            pie_data_start_row = 3  # Start the pie chart from the 2nd row

            # Add the data for the pie chart and table in one go
            item_heading = analytics_sheet.cell(row=pie_data_start_row, column=9, value="Item")
            amount_heading = analytics_sheet.cell(row=pie_data_start_row, column=8, value="Amount")
            count_heading = analytics_sheet.cell(row=pie_data_start_row, column=10, value="Count")

            # Set headings to bold and center alignment
            bold_font = Font(bold=True)
            center_alignment = Alignment(horizontal='center', vertical='center')

            item_counts = {item: sum(1 for row in results if row[1] == item) for item in item_amounts}

            for idx, (item, amount) in enumerate(top_items, start=1):
                amount_cell = analytics_sheet.cell(row=pie_data_start_row + idx, column=8, value=amount)
                count_cell = analytics_sheet.cell(row=pie_data_start_row + idx, column=10, value=item_counts[item])

            # Apply border to the headings
            item_heading.border = thin_border
            amount_heading.border = thin_border
            count_heading.border = thin_border

            # Add pie chart
            pie_chart = PieChart()
            labels = Reference(analytics_sheet, min_col=9, min_row=pie_data_start_row + 1, max_row=pie_data_start_row + len(top_items))

            # Calculate total amount from the "Expenses" sheet
            total_amount_expenses_sheet = sum(
                cell.value for column in sheet.iter_cols(min_col=2, min_row=3, max_col=2, max_row=sheet.max_row)
                for cell in column if cell.value is not None
            )

            # Update the percentages based on the total amount from the "Expenses" sheet
            combined_labels = []
            for idx, (item, amount) in enumerate(top_items, start=1):
                percentage = (amount / total_amount_expenses_sheet) * 100 * 2
                combined_label = f"{item} ({percentage:.2f}%)"
                combined_labels.append(combined_label)
                combined_label_cell = analytics_sheet.cell(row=pie_data_start_row + idx, column=9, value=combined_label)
                combined_label_cell.border = thin_border

                # Add pie chart
                pie_chart = PieChart()
                labels = Reference(analytics_sheet, min_col=9, min_row=pie_data_start_row + 1, max_row=pie_data_start_row + len(top_items))
                data = Reference(analytics_sheet, min_col=8, min_row=pie_data_start_row + 1, max_row=pie_data_start_row + len(top_items))
                pie_chart.add_data(data, titles_from_data=False)
                pie_chart.set_categories(labels)
                pie_chart.style = 10

                # Configure data labels to show item names and percentages
                data_labels = DataLabelList()
                data_labels.showCatName = True
                data_labels.showVal = False
                data_labels.showPercent = False  # Turn off the default percentage
                data_labels.dLblPos = 'outEnd'  # Labels outside the pie chart
                data_labels.showLeaderLines = False  # Enable leader lines
                pie_chart.dataLabels = data_labels

                # Disable the legend
                pie_chart.legend = None

                # Place the pie chart starting at the 2nd row, middle of column A
                pie_chart_anchor = f"A3"
                analytics_sheet.add_chart(pie_chart, pie_chart_anchor)

        excel_file_path = f".\\Exports\\{file_name}"
        workbook.save(excel_file_path)

        self.statusBar.showMessage(f"Export to Excel completed. File saved as {excel_file_path}", 3000)
        webbrowser.open(excel_file_path)

    else:
        QtWidgets.QMessageBox.information(self, "Export to Excel", "No data to export.") 

问题:

  • 我需要删除饼图中的“Series1”标签。
  • 在ie_chart.add_data(data,titles_from_data = False)中设置titles_from_data = False不会关闭“Series1”。

这是我要删除的带有“Series1”标签的饼图图像 enter image description here


以下是使用 openpyxl 从 Python 中的饼图中删除“Series 1”标签的方法:

问题在于,即使通过设置 titles_from_data=False 禁用了数据点标签,openpyxl 仍然默认包含图例。由于只有一个数据系列(因此命名为“Series 1”),该图例看起来就像一个不必要的标签。

需要做的是 完全禁用该图例 。以下是更新后的代码:

# ...(之前的代码)...

# 添加饼图
pie_chart = PieChart()
labels = Reference(analytics_sheet, min_col=9, min_row=pie_data_start_row + 1, max_row=pie_data_start_row + len(top_items))
data = Reference(analytics_sheet, min_col=8, min_row=pie_data_start_row + 1, max_row=pie_data_start_row + len(top_items))
pie_chart.add_data(data, titles_from_data=False)
pie_chart.set_categories(labels)
pie_chart.style = 10

# 配置数据标签以显示项目名称和百分比
data_labels = DataLabelList()
data_labels.showCatName = True
data_labels.showVal = False
data_labels.showPercent = False  # 关闭默认百分比
data_labels.dLblPos = 'outEnd'  # 标签在饼图外部
data_labels.showLeaderLines = False  # 启用引导线
pie_chart.dataLabels = data_labels

# 禁用图例
pie_chart.legend = None

# 将饼图放置在从第二行开始的 A 列中间
pie_chart_anchor = f"A3"
analytics_sheet.add_chart(pie_chart, pie_chart_anchor)

# ...(之后的代码)... 

通过将 pie_chart.legend = None 添加到的代码中,将完全禁用图例,从而有效地删除“Series 1”标签。这将为提供一个更清晰、更简洁的饼图,没有任何不必要的标签。

标签:python,charts,openpyxl,excel-charts
From: 78799469

相关文章

  • 在python3.8虚拟环境 执行pip 安装Excel的库
    1、在开始菜单打开Anacondaprompt(anaconda3) 2、查看环境列表 3、进入虚拟环境 4、在虚拟换进下使用清华源安装读取excel的库和写入excel的库读取Excel文件的库:pipinstallxlrd-ihttps://pypi.tuna.tsinghua.edu.cn/simple 写入Excel文件的库:pipinstallxlwt......
  • Python Pandas 使用 .loc 跨列级别多重索引
    我对python和pandas仍然很陌生,想知道是否有更好的方法来解决我遇到的索引问题。因为我看到人们在这个网站上做了非常巧妙的事情,超出了我通常可以从文档中收集到的内容,所以我想我会问——特别是因为我还在学习。我有一个包含多个列的DataFrame级别,级别0是“meta”和“r......
  • Python、Scapy 并导出到 .exe
    目前我会玩一点scapy、Qt和python。到目前为止,使用VSC启动程序时一切正常。现在我尝试使用PyInstaller制作.exe。它也有效,我得到了一个.exe文件,可以打开它并显示我的Qt-Windows。但是当我使用scapy函数时,程序崩溃,没有任何消息,并且窗口关闭。我激活了日志记录并发......
  • 使用 python 检测鼠标是等待还是忙碌
    我正在用Python2.7创建一个脚本。该脚本在应用程序内自动执行鼠标单击。有一些情况,在单击鼠标后,鼠标光标将“等待”,我想等到鼠标光标恢复正常后再进行操作我进入代码中的下一步。Python中是否可以检测鼠标是否正在等待?在Python中没有内置方法可以检测......
  • ValueError:在带有 GATT 的 Python 中,以 16 为基数的 int() 的文字无效:b'0f 18 '
    我正在使用Python和GATT库pxexpect来处理一些数据,但在尝试将十六进制值转换为整数时遇到问题。这是我看到的具体错误:print(int(gatt.before,16)),^^^^^^^^^^^^^^^^^^^^ValueError:invalidliteralforint()withbase16:b'0f18'这是产生错误的代......
  • 我看不懂这个python脚本?
    用于加载.dat文件的Python脚本importcsvfromdjango.core.management.baseimportBaseCommandfromrecommender.modelsimportUser,Artist,Tag,UserArtist,UserTaggedArtist,UserFriendimportosfromdjango.confimportsettings#Definethepathtothedatab......
  • 使用操作系统工具通过 Python 3 扫描图像
    我正在使用python构建一个应用程序,它需要能够连接到扫描仪并处理生成的pdf/jpeg/其他文件中的数据。我一直在尝试找到一种连接到扫描仪以请求扫描的方法,但没有真正的进展。我已经查看了我能找到的所有选项,包括这个答案:我想连接我的图像扫描仪程序我发现的大多......
  • Python,pandas从字符串中解析数字和字符串
    在Python中,我想解析一个字符串并将数字部分(可能有也可能没有小数点)作为浮点数返回,并将后缀作为字符串返回。示例为:7.1英寸->7.1,英寸7.1”->7.1,“7英寸->7.0,英寸-10dB->-10.0,dB-10.2dB->-10.2,dB数字部分和后缀之间没有空格。另外,我想将其应......
  • 如何在 Python 中加载站点的所有资源,包括 AJAX 请求等?
    我知道如何使用Python请求网站并读取其文本。过去,我曾尝试使用像BeautifulSoup这样的库来发出对网站上链接的所有请求,但这并没有得到看起来不像完整URL的内容,例如AJAX请求和大多数对原始域(因为“http://example.com”将丢失,更重要的是,它不是<ahref='url'>......
  • 使用Python进行PDF旋转
    使用python旋转扫描的pdf后,它工作得很好,但将pdf发送给第三方后,第三方仍然将pdf检测为90度pdf有什么办法可以解决旋转和这个问题importPyPDF2withopen('input.pdf','rb')asfile:#CreateaPDFreaderobjectreader=PyPDF2.PdfReader(file)......