openpyxl绘制堆叠图

2023-11-07

本文将会说明如何用openpyxl绘制堆叠图,先来看看效果图

数据处理后效果展示:

源数据:

老规矩源代码先放上后面再解析,使用时记得要改一下路径哦

# 先把openpyxl全家桶安排上
from openpyxl import load_workbook
from openpyxl.utils import get_column_letter
from openpyxl.chart.axis import ChartLines
from openpyxl.chart.shapes import GraphicalProperties
from openpyxl.chart import BarChart, Reference, label as chart_label
from openpyxl.chart.text import RichText
from openpyxl.drawing.text import Paragraph, ParagraphProperties, CharacterProperties, Font as ChartFont
from openpyxl.drawing.line import LineProperties

from collections import OrderedDict    # 这个用来统计标签

class PictureHandler(object):
    def __init__(self, input, output, origin_sheet='源数据', picture_sheet='画像'):
        self.input = input
        self.output = output

        self.origin_sheet = origin_sheet
        self.picture_sheet = picture_sheet

    '''设置图像格式(这部分可直接忽略,主要看下面的add_chart函数)'''
    def create_bar_chart(self,sheet, begin_row, end_row):
        chart = BarChart()
        chart.height = 7
        chart.width = 14
        chart.type = "col"
        chart.style = 2
        chart.title = sheet.cell(row=begin_row, column=1).value
        # chart1.y_axis.title = 'Test number'
        # chart1.x_axis.title = 'Sample length (mm)'

        # 图表数据
        data = Reference(sheet, min_col=sheet.min_column + 1, max_col=sheet.max_column, min_row=begin_row,
                         max_row=end_row)
        # from_rows: 当值为True时,一行是一个系列,为False时,一列是一个系列
        # titles_from_data: 当值为True时,data包含系列名称
        chart.add_data(data, titles_from_data=True, from_rows=True)

        # x轴标签
        cats = Reference(sheet, min_col=sheet.min_column + 2, max_col=sheet.max_column, min_row=sheet.min_row,
                         max_row=sheet.min_row)
        chart.set_categories(cats)

        # 添加数字标签
        chart.dLbls = chart_label.DataLabelList()
        chart.dLbls.showVal = True

        chart.grouping = "percentStacked"  # 设置为百分比堆叠图
        chart.overlap = 100  # 当为堆叠图时需要设置为100
        chart.y_axis.scaling.min = 0  # 设置y轴最大值为0
        chart.y_axis.scaling.max = 1  # 设置y轴最大值为1

        font_test = ChartFont(typeface='微软雅黑')
        cp = CharacterProperties(latin=font_test)
        chart.y_axis.textProperties = RichText(p=[Paragraph(pPr=ParagraphProperties(defRPr=cp), endParaRPr=cp)])
        chart.x_axis.textProperties = RichText(p=[Paragraph(pPr=ParagraphProperties(defRPr=cp), endParaRPr=cp)])
        chart.legend.textProperties = RichText(p=[Paragraph(pPr=ParagraphProperties(defRPr=cp), endParaRPr=cp)])
        chart.dLbls.textProperties = RichText(p=[Paragraph(pPr=ParagraphProperties(defRPr=cp), endParaRPr=cp)])
        chart.y_axis.delete = True  # 设置隐藏y轴标签

        # 设置隐藏网格线
        chart.y_axis.majorGridlines = ChartLines()
        sgp = GraphicalProperties(ln=LineProperties(noFill=True))
        chart.y_axis.majorGridlines.spPr = sgp

        return chart

    def add_chart(self):
        workbook = load_workbook(self.output)
        sheet = workbook[self.picture_sheet]

        # 根据第一列标签名称,统计各标签分别有多少行数据
        label_dict = OrderedDict()
        for row_num in range(2, sheet.max_row + 1):
            label = sheet.cell(row=row_num, column=1).value
            label_dict[label] = label_dict.get(label, 0) + 1

        # 生成图表
        begin_row = 2
        for index, (label, row_num) in enumerate(label_dict.items()):
            # 确定标签的数据起始行、结束行
            end_row = begin_row + row_num - 1
            chart = self.create_bar_chart(sheet, begin_row=begin_row, end_row=end_row)
            begin_row += row_num

            # 确定图表放置位置
            chart_row_num = 14 * (index // 2) + 1
            if index % 2 == 0:
                chart_col_num = sheet.max_column + 2
            else:
                chart_col_num = sheet.max_column + 10
            chart_position = get_column_letter(chart_col_num) + str(chart_row_num)
            sheet.add_chart(chart, chart_position)

        workbook.save(self.output)


    def start(self):
        self.add_chart()


if __name__ == '__main__':
    input_file = f'输入数据.xlsx'
    output_file = f'输出画像.xlsx'
    picture_handler = PictureHandler(input=input_file, output=output_file)
    picture_handler.start()

代码解析:

第一步:导入openpyxl要用到的模块,以及collections中的OrderedDict(这个主要用来统计各个标签)

第二步:确定待绘制画像的格式、标签及数据,将画像的格式初始化

第三步:确定画像的摆放(起始位置)等等

第四步:绘制图案并保存

整体架构:

class PictureHandler(object):
    def __init__(self, input, output, origin_sheet='源数据', picture_sheet='画像'):
        self.input = input
        self.output = output

        self.origin_sheet = origin_sheet
        self.picture_sheet = picture_sheet


    # 设置图像格式(这部分可直接忽略,主要看下面的add_chart函数)
    def create_bar_chart(self,sheet, begin_row, end_row):

    # 确定画像位置、绘图
    def add_chart(self):

    def start(self):
        self.add_chart()

if __name__ == '__main__':
    input_file = f'test_input备份 - 副本.xlsx'
    output_file = f'test_input画像.xlsx'
    picture_handler = PictureHandler(input=input_file, output=output_file)
    picture_handler.start()

导入模块:

from openpyxl import load_workbook
from openpyxl.utils import get_column_letter

from openpyxl.chart.axis import ChartLines
from openpyxl.chart.shapes import GraphicalProperties
from openpyxl.chart import BarChart, Reference, label as chart_label
from openpyxl.chart.text import RichText
from openpyxl.drawing.text import Paragraph, ParagraphProperties, CharacterProperties, Font as ChartFont
from openpyxl.drawing.line import LineProperties

from collections import OrderedDict    # 用来统计标签

设置画像格式

    def create_bar_chart(self,sheet, begin_row, end_row):
        chart = BarChart()
        chart.height = 7
        chart.width = 14
        chart.type = "col"
        chart.style = 2
        chart.title = sheet.cell(row=begin_row, column=1).value
        # chart1.y_axis.title = 'Test number'
        # chart1.x_axis.title = 'Sample length (mm)'

        # 图表数据
        data = Reference(sheet, min_col=sheet.min_column + 1, max_col=sheet.max_column, min_row=begin_row,
                         max_row=end_row)
        # from_rows: 当值为True时,一行是一个系列,为False时,一列是一个系列
        # titles_from_data: 当值为True时,data包含系列名称
        chart.add_data(data, titles_from_data=True, from_rows=True)

        # x轴标签
        cats = Reference(sheet, min_col=sheet.min_column + 2, max_col=sheet.max_column, min_row=sheet.min_row,
                         max_row=sheet.min_row)
        chart.set_categories(cats)

        # 添加数字标签
        chart.dLbls = chart_label.DataLabelList()
        chart.dLbls.showVal = True

        chart.grouping = "percentStacked"  # 设置为百分比堆叠图
        chart.overlap = 100  # 当为堆叠图时需要设置为100
        chart.y_axis.scaling.min = 0  # 设置y轴最大值为0
        chart.y_axis.scaling.max = 1  # 设置y轴最大值为1

        font_test = ChartFont(typeface='微软雅黑')
        cp = CharacterProperties(latin=font_test)
        chart.y_axis.textProperties = RichText(p=[Paragraph(pPr=ParagraphProperties(defRPr=cp), endParaRPr=cp)])
        chart.x_axis.textProperties = RichText(p=[Paragraph(pPr=ParagraphProperties(defRPr=cp), endParaRPr=cp)])
        chart.legend.textProperties = RichText(p=[Paragraph(pPr=ParagraphProperties(defRPr=cp), endParaRPr=cp)])
        chart.dLbls.textProperties = RichText(p=[Paragraph(pPr=ParagraphProperties(defRPr=cp), endParaRPr=cp)])
        chart.y_axis.delete = True  # 设置隐藏y轴标签

        # 设置隐藏网格线
        chart.y_axis.majorGridlines = ChartLines()
        sgp = GraphicalProperties(ln=LineProperties(noFill=True))
        chart.y_axis.majorGridlines.spPr = sgp

        return chart

确定摆放位置

统计标签的数据,确定数据的起始行与结束行,然后计算出图表的摆放位置

workbook = load_workbook(self.output)
        sheet = workbook[self.picture_sheet]

        # 根据第一列标签名称,统计各标签分别有多少行数据
        label_dict = OrderedDict()
        for row_num in range(2, sheet.max_row + 1):
            label = sheet.cell(row=row_num, column=1).value
            label_dict[label] = label_dict.get(label, 0) + 1

        # 生成图表
        begin_row = 2
        for index, (label, row_num) in enumerate(label_dict.items()):
            # 确定标签的数据起始行、结束行
            end_row = begin_row + row_num - 1
            chart = self.create_bar_chart(sheet, begin_row=begin_row, end_row=end_row)
            begin_row += row_num

            # 确定图表放置位置
            chart_row_num = 14 * (index // 2) + 1
            if index % 2 == 0:
                chart_col_num = sheet.max_column + 2
            else:
                chart_col_num = sheet.max_column + 10

绘制画像

    def add_chart(self):
        workbook = load_workbook(self.output)
        sheet = workbook[self.picture_sheet]

        # 根据第一列标签名称,统计各标签分别有多少行数据
        label_dict = OrderedDict()
        for row_num in range(2, sheet.max_row + 1):
            label = sheet.cell(row=row_num, column=1).value
            label_dict[label] = label_dict.get(label, 0) + 1

        # 生成图表
        begin_row = 2
        for index, (label, row_num) in enumerate(label_dict.items()):
            # 确定标签的数据起始行、结束行
            end_row = begin_row + row_num - 1
            chart = self.create_bar_chart(sheet, begin_row=begin_row, end_row=end_row)
            begin_row += row_num

            # 确定图表放置位置
            chart_row_num = 14 * (index // 2) + 1
            if index % 2 == 0:
                chart_col_num = sheet.max_column + 2
            else:
                chart_col_num = sheet.max_column + 10
            chart_position = get_column_letter(chart_col_num) + str(chart_row_num)
            sheet.add_chart(chart, chart_position)

        workbook.save(self.output)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

openpyxl绘制堆叠图 的相关文章

随机推荐

  • Dyanmics CRM您无法登陆系统。原因可能是您的用户记录或所属的业务部门在Microoft Dynamics CRM中已被禁用...

    当在操作CRM时 做任何的写操作包括创建数据 更新数据 都会提示下面截图中的错误 您无法登陆系统 原因可能是您的用户记录或所属的业务部门在Microoft Dynamics CRM中已被禁用 根据错误提示第一反应就是当前操作用户的业务部门被
  • sqlalchemy order_by降序/升序

    sqlalchemy中的query默认是按id升序进行排序的 当遇到复杂情况时就需要时用order by 下面介绍几种order by 的几种使用方法 session query User order by User create time
  • Cpp学习——string(2)

    目录 编辑 容器string中的一些函数 1 capacity 2 reserve 3 resize 4 push back 与append 5 find系列函数 容器string中的一些函数 1 capacity capacity是str
  • git上传文件到github的操作流程

    git上传文件到github的操作流程 下载git之后 新建空白文件 右键找到git bash打开 如果电脑第一次安装 输入命令 git config global user name github上面的名称 git config glob
  • WPF 使用自定义控件(custom control),资源字典(ResourceDictionary),用户控件(user control),及之间的对比

    最近使用WPF比较多 过来记录一下 对比一下 个人理解usercontrol比较适用于组合控件 比如你想要实现的控件是由多个控件组成的 customCcontrol主要是用来单独重绘控件 如button datagrid lable等 cu
  • 牛客SQL进阶:【字符串的切割、截取、删除、替换】+【窗口函数】

    本文总结了牛客SQL刷题 非技术快速入门的进阶知识 阅读本文可以轻松解决这个系列下的难题 SQL30 统计每种性别的人数 SQL31 提取博客URL中的用户名 字符串拆分 有分隔符 字符串拆分 无分隔符 SQL32 截取出年龄 SQL33
  • vue3对echarts的二次封装之按需加载

    欢迎点击领取 前端面试题进阶指南 前端登顶之巅 最全面的前端知识点梳理总结 分享一个使用比较久的 效果展示 1 echarts是我们后台系统中最常用的数据统计图形展示 外界对它的二次封装也不计层数 2 在业务代码内每次的初始dom和绑定se
  • np.eye()函数

    np eye 的函数 除了生成对角阵外 还可以将一个label数组 大小为 1 m 或者 m 1 的数组 转化成one hot数组 例如它可以将类别总数为6的labels 1 2 3 0 1 1 的数组转化成数组 0 1 0 0 0 0 0
  • Android 执行 gradle test 出错: JAVA_HOME is not set and no 'java' command could be found in your PATH.

    AndroidStudio Terminal控制台 执行 gradle test 出错 JAVA HOME is not set and no java command could be found in your PATH 找到JDK和g
  • Linux下使用gtest对接口进行单元测试

    目录 1 背景 2 gtest 断言 2 1 布尔值判断 2 2 二进制比较 2 3 字符串比较 2 4 浮点数比较 3 实践 3 1 框架使用 3 2 用例编写 3 3 编译运行 4 结论 1 背景 工程中涉及基础接口的设计 为了保证接口
  • pytorch学习笔记——2.5Pytorch中数据操作和预处理

    前言 在torch utils data模块中包含一些常用的数据预处理的操作 比如数据的读取 切分 准备等 通过使用这些类 我们可以对高维数组 图像等各种类型的数据进行预处理 以便在深度学习模型中使用 在本文中 我们主要介绍回归模型和分类模
  • Window.iso镜像文件下载

    Window iso镜像文件下载 https www microsoft com zh cn software download windows10 Window iso官网下载地址 一 使用MediaCreationTool20H2官方工
  • MCU(单片机)datasheet(规格说明书)

    STC 宏晶 型号 程序容量 datasheet STC8G2K64S4 36I QFN48 64K 规格说明书链接 https pan baidu com s 18IickcTlMHgesCkmXFi7Lg pwd tala 提取码 ta
  • gcc、g++、make、cmake区别

    首先介绍一下GCC GNU Compiler Collection GNU 编译器集合 在为Linux开发应用程序时 绝大多数情况下使用的都是C语言 因此几乎每一位Linux程序员面临的首要问题都是如何灵活运用C编译器 目前 Linux下最
  • 【游戏测试工程师】2023年4399秋招笔试+面试记录

    文章目录 一 笔试题 一 逻辑推理题 1 猜花色 2 猜岗位 二 游戏测试相关题 1 假如你要对一款手机游戏进行基本测试 问 一 你会做哪几个方面的测试 二 分别想怎么做 2 编写游戏测试用例 3 编写测试点 三 编程题 1 游戏竞技场 2
  • java swing GUI窗口美化

    一般我们写出的窗口是这个样子的 文本框和按钮都不是太美观 如果按钮是原色的就更难看了 今天发现了一个更加美观的窗口模式 可以发现按钮和文本框都已经有了变化 给窗口润色不少 其实 只需在调用程序前加上这段代码即可 try for javax
  • Atom+Asciidoctor+Antora环境搭建

    个人博客原文链接 Atom 简介 Atom是github专门为程序员推出的一个跨平台文本编辑器 具有简洁和直观的图形用户界面 并有很多有趣的特点 支持CSS HTML JavaScript等网页编程语言 它支持宏 自动完成分屏功能 集成了文
  • LeetCode——040

    40 Combination Sum II My Submissions QuestionEditorial Solution Total Accepted 66386 Total Submissions 241547 Difficulty
  • 搭建Mybatis注意事项和实现原理,你真的看懂了吗?

    搭建Mybatis环境注意事项 一 搭建Mybatis环境注意事项 二 涉及到的设计模式 2 1工厂模式 SqlSessionFactory 2 2 代理模式 MapperProxyFactory 2 3构建者模式 SqlSessionFa
  • openpyxl绘制堆叠图

    本文将会说明如何用openpyxl绘制堆叠图 先来看看效果图 数据处理后效果展示 源数据 老规矩源代码先放上后面再解析 使用时记得要改一下路径哦 先把openpyxl全家桶安排上 from openpyxl import load work