# -*- coding: utf-8 -*-
import os
import cx_Oracle as cx
import pandas as pd
import datetime as dt
import schedule
import time
import requests
from threading import Thread
import base64
import hashlib
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Rectangle
class Wechat:
def __init__(self, secret):
self.secret = secret
def access_token(self):
"""获取企业微信access_token"""
url = f'https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=wwed5e7f3fd1a3a553&corpsecret={self.secret}'
response = requests.get(url).json()
return response['access_token']
def oracle_connect(sql):
"""Oracle数据库连接查询"""
con = cx.connect("admin/xxb20140415@192.168.3.16:1521/zzjdata")
cursor = con.cursor()
cursor.execute(sql)
column_s = [col[0] for col in cursor.description]
data = cursor.fetchall()
cursor.close()
con.close()
return data, column_s
def generate_store_performance_sql():
"""生成门店绩效环比数据SQL"""
sql = """
select a.c_mdfq 大区,a.c_dq 地市,a.c_mdfq1 地区,a.tjbh 门店编码,a.mc 门店名称,b.lb 类别,nvl(b.jshj,0) 本周销售,nvl(b.ml,0) 本周毛利,nvl(c.jshj,0) 上周销售,nvl(c.ml,0) 上周毛利
from (select a.subbh,nvl(e.sx,'未分类') lb,sum(a.jshj) jshj,sum(a.zhml) ml
from c_zkmtmdspxshzb a left join (select * from spjxlbz where lbz='1') e on e.hh=a.hh
where a.kdrq BETWEEN TRUNC(SYSDATE, 'IW') AND TRUNC(SYSDATE-1)
group by a.subbh,nvl(e.sx,'未分类')) b
left join (select a.subbh,nvl(e.sx,'未分类') lb,sum(a.jshj) jshj,sum(a.zhml) ml
from c_zkmtmdspxshzb a left join (select * from spjxlbz where lbz='1') e on e.hh=a.hh where a.kdrq BETWEEN TRUNC(SYSDATE, 'IW') - 7 AND TRUNC(SYSDATE- 1) - 7
group by a.subbh,nvl(e.sx,'未分类')) c on b.subbh=c.subbh and b.lb=c.lb
left join gl_custom a on a.tjbh=b.subbh and a.tjbh=c.subbh
where a.c_mdfq <>' 'and a.c_dq<>' ' and a.c_mdfq1<>' ' and a.c_mdfq <>'电商' and a.c_mdfq <>'大客户部'
and a.c_mdfq <>'海南地区' and a.c_mdfq <>'黑龙江地区'
"""
return sql
def calculate_growth_rate(current_value, last_value):
"""计算环比增长率"""
if last_value == 0:
return 0
return round((current_value - last_value) / last_value * 100, 2)
def calculate_profit_margin(sales, profit):
"""计算毛利率"""
if sales == 0:
return 0
return round(profit / sales * 100, 2)
def format_growth_rate(growth_rate):
"""格式化环比增长率显示:负数加负号,正数不加正号"""
if growth_rate > 0:
return f"{growth_rate:.2f}%"
elif growth_rate < 0:
return f"{growth_rate:.2f}%"
else:
return "0.00%"
def transform_data_for_region_comparison(df):
"""转换数据为大区环比对比表格式(转置后)- 合并类别项,并添加合计列"""
try:
print(f"原始数据行数: {len(df)}")
print(f"大区列表: {sorted(df['大区'].unique())}")
print(f"类别列表: {sorted(df['类别'].unique())}")
categories = sorted(df['类别'].unique())
regions = sorted(df['大区'].unique())
result_data = []
# 全国总计
total_current_sales = df['本周销售'].sum()
total_last_sales = df['上周销售'].sum()
total_current_profit = df['本周毛利'].sum()
total_last_profit = df['上周毛利'].sum()
total_sales_growth = calculate_growth_rate(total_current_sales, total_last_sales)
total_profit_growth = calculate_growth_rate(total_current_profit, total_last_profit)
total_current_margin = calculate_profit_margin(total_current_sales, total_current_profit)
total_last_margin = calculate_profit_margin(total_last_sales, total_last_profit)
total_margin_growth = calculate_growth_rate(total_current_margin, total_last_margin)
# 为每个类别处理
for category in categories:
cat_df = df[df['类别'] == category]
# 类别内全国数据
cat_current_sales = cat_df['本周销售'].sum()
cat_last_sales = cat_df['上周销售'].sum()
cat_current_profit = cat_df['本周毛利'].sum()
cat_last_profit = cat_df['上周毛利'].sum()
cat_sales_growth = calculate_growth_rate(cat_current_sales, cat_last_sales)
cat_profit_growth = calculate_growth_rate(cat_current_profit, cat_last_profit)
cat_current_margin = calculate_profit_margin(cat_current_sales, cat_current_profit)
cat_last_margin = calculate_profit_margin(cat_last_sales, cat_last_profit)
cat_margin_growth = calculate_growth_rate(cat_current_margin, cat_last_margin)
# 销售、毛利、毛利率三行(用于表格)
sales_row = {'类别': category, '指标': '销售环比', 'row_type': 'category_start'}
profit_row = {'类别': '', '指标': '毛利环比', 'row_type': 'category_middle'}
margin_row = {'类别': '', '指标': '毛利率环比', 'row_type': 'category_end'}
# 计算每个大区 + 合计
for region in regions:
region_cat_df = cat_df[cat_df['大区'] == region]
rcs = region_cat_df['本周销售'].sum()
rls = region_cat_df['上周销售'].sum()
rcp = region_cat_df['本周毛利'].sum()
rlp = region_cat_df['上周毛利'].sum()
rcm = calculate_profit_margin(rcs, rcp)
rlm = calculate_profit_margin(rls, rlp)
sg = calculate_growth_rate(rcs, rls)
pg = calculate_growth_rate(rcp, rlp)
mg = calculate_growth_rate(rcm, rlm)
sales_row[region] = format_growth_rate(sg)
profit_row[region] = format_growth_rate(pg)
margin_row[region] = format_growth_rate(mg)
# 🔽 新增:该类别所有大区平均/加权?这里采用销售额加权平均
# 简单做法:取所有门店汇总后的整体增长率(已在上面计算过 cat_sales_growth)
sales_row['合计'] = format_growth_rate(cat_sales_growth)
profit_row['合计'] = format_growth_rate(cat_profit_growth)
margin_row['合计'] = format_growth_rate(cat_margin_growth)
result_data.extend([sales_row, profit_row, margin_row])
# 🔽 总计行(所有类别汇总)
total_sales_row = {'类别': '总计', '指标': '销售环比', 'row_type': 'total_start'}
total_profit_row = {'类别': '', '指标': '毛利环比', 'row_type': 'total_middle'}
total_margin_row = {'类别': '', '指标': '毛利率环比', 'row_type': 'total_end'}
for region in regions:
region_df = df[df['大区'] == region]
rcs = region_df['本周销售'].sum()
rls = region_df['上周销售'].sum()
rcp = region_df['本周毛利'].sum()
rlp = region_df['上周毛利'].sum()
rcm = calculate_profit_margin(rcs, rcp)
rlm = calculate_profit_margin(rls, rlp)
sg = calculate_growth_rate(rcs, rls)
pg = calculate_growth_rate(rcp, rlp)
mg = calculate_growth_rate(rcm, rlm)
total_sales_row[region] = format_growth_rate(sg)
total_profit_row[region] = format_growth_rate(pg)
total_margin_row[region] = format_growth_rate(mg)
# 总计行的合计列
total_sales_row['合计'] = format_growth_rate(total_sales_growth)
total_profit_row['合计'] = format_growth_rate(total_profit_growth)
total_margin_row['合计'] = format_growth_rate(total_margin_growth)
result_data.extend([total_sales_row, total_profit_row, total_margin_row])
columns = ['类别', '指标'] + regions + ['合计']
result_df = pd.DataFrame(result_data)[columns]
print(f"大区对比表形状: {result_df.shape}")
return result_df, categories, regions, result_data
except Exception as e:
print(f"大区数据转换失败: {str(e)}")
import traceback
traceback.print_exc()
return None, None, None, None
def transform_data_for_city_comparison(df, target_region):
"""转换数据为指定大区的地市环比对比表格式(转置后)- 合并类别项"""
try:
region_df = df[df['大区'] == target_region]
print(f"处理大区 {target_region}, 数据行数: {len(region_df)}")
categories = sorted(region_df['类别'].unique())
cities = sorted(region_df['地市'].unique())
print(f"地市列表: {cities}")
print(f"类别列表: {categories}")
# 准备转置后的数据结构
result_data = []
# 计算大区合计数据
region_current_sales = region_df['本周销售'].sum()
region_last_sales = region_df['上周销售'].sum()
region_current_profit = region_df['本周毛利'].sum()
region_last_profit = region_df['上周毛利'].sum()
region_current_margin = calculate_profit_margin(region_current_sales, region_current_profit)
region_last_margin = calculate_profit_margin(region_last_sales, region_last_profit)
region_sales_growth = calculate_growth_rate(region_current_sales, region_last_sales)
region_profit_growth = calculate_growth_rate(region_current_profit, region_last_profit)
region_margin_growth = calculate_growth_rate(region_current_margin, region_last_margin)
# 为每个类别添加三行数据
for category in categories:
# 获取该类别数据
cat_df = region_df[region_df['类别'] == category]
# 计算大区该类别数据
cat_current_sales = cat_df['本周销售'].sum()
cat_last_sales = cat_df['上周销售'].sum()
cat_current_profit = cat_df['本周毛利'].sum()
cat_last_profit = cat_df['本周毛利'].sum()
# 销售环比行 - 合并类别,同一类别只显示一次
sales_row = {'类别': category, '指标': '销售环比', 'row_type': 'category_start'}
# 毛利环比行 - 类别留空
profit_row = {'类别': '', '指标': '毛利环比', 'row_type': 'category_middle'}
# 毛利率环比行 - 类别留空
margin_row = {'类别': '', '指标': '毛利率环比', 'row_type': 'category_end'}
# 为每个地市计算数据
for city in cities:
city_cat_df = cat_df[cat_df['地市'] == city]
# 当前地市该类别数据
city_current_sales = city_cat_df['本周销售'].sum()
city_last_sales = city_cat_df['上周销售'].sum()
city_current_profit = city_cat_df['本周毛利'].sum()
city_last_profit = city_cat_df['上周毛利'].sum()
city_current_margin = calculate_profit_margin(city_current_sales, city_current_profit)
city_last_margin = calculate_profit_margin(city_last_sales, city_last_profit)
# 计算环比
sales_growth = calculate_growth_rate(city_current_sales, city_last_sales)
profit_growth = calculate_growth_rate(city_current_profit, city_last_profit)
margin_growth = calculate_growth_rate(city_current_margin, city_last_margin)
# 填充数据
sales_row[city] = f"{sales_growth:+.2f}%"
profit_row[city] = f"{profit_growth:+.2f}%"
margin_row[city] = f"{margin_growth:+.2f}%"
# 添加大区合计数据
cat_sales_growth = calculate_growth_rate(cat_current_sales, cat_last_sales)
cat_profit_growth = calculate_growth_rate(cat_current_profit, cat_last_profit)
cat_current_margin = calculate_profit_margin(cat_current_sales, cat_current_profit)
cat_last_margin = calculate_profit_margin(cat_last_sales, cat_last_profit)
cat_margin_growth = calculate_growth_rate(cat_current_margin, cat_last_margin)
sales_row[f'{target_region}合计'] = f"{cat_sales_growth:+.2f}%"
profit_row[f'{target_region}合计'] = f"{cat_profit_growth:+.2f}%"
margin_row[f'{target_region}合计'] = f"{cat_margin_growth:+.2f}%"
result_data.extend([sales_row, profit_row, margin_row])
# 添加总计行 - 总计行也合并显示
total_sales_row = {'类别': '总计', '指标': '销售环比', 'row_type': 'total_start'}
total_profit_row = {'类别': '', '指标': '毛利环比', 'row_type': 'total_middle'}
total_margin_row = {'类别': '', '指标': '毛利率环比', 'row_type': 'total_end'}
for city in cities:
city_df = region_df[region_df['地市'] == city]
city_current_sales = city_df['本周销售'].sum()
city_last_sales = city_df['上周销售'].sum()
city_current_profit = city_df['本周毛利'].sum()
city_last_profit = city_df['上周毛利'].sum()
city_current_margin = calculate_profit_margin(city_current_sales, city_current_profit)
city_last_margin = calculate_profit_margin(city_last_sales, city_last_profit)
sales_growth = calculate_growth_rate(city_current_sales, city_last_sales)
profit_growth = calculate_growth_rate(city_current_profit, city_last_profit)
margin_growth = calculate_growth_rate(city_current_margin, city_last_margin)
total_sales_row[city] = f"{sales_growth:+.2f}%"
total_profit_row[city] = f"{profit_growth:+.2f}%"
total_margin_row[city] = f"{margin_growth:+.2f}%"
total_sales_row[f'{target_region}合计'] = f"{region_sales_growth:+.2f}%"
total_profit_row[f'{target_region}合计'] = f"{region_profit_growth:+.2f}%"
total_margin_row[f'{target_region}合计'] = f"{region_margin_growth:+.2f}%"
result_data.extend([total_sales_row, total_profit_row, total_margin_row])
# 构建DataFrame
columns = ['类别', '指标'] + cities + [f'{target_region}合计']
result_df = pd.DataFrame(result_data)[columns]
print(f"地市对比表形状: {result_df.shape}")
return result_df, categories, cities, result_data
except Exception as e:
print(f"地市数据转换失败: {str(e)}")
import traceback
traceback.print_exc()
return None, None, None, None
def create_table_image(df, title, output_path, categories, regions, raw_data=None):
"""使用matplotlib创建转置表格图片,正确实现类别合并与居中"""
try:
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
# 构建表头
header = ['类别', '指标'] + list(regions) + ['合计'] # 包含合计列
table_data = []
for _, row in df.iterrows():
row_data = [row['类别'], row['指标']]
for col in regions + ['合计']:
row_data.append(row.get(col, '-'))
table_data.append(row_data)
n_rows = len(table_data) + 1
n_cols = len(header)
fig_height = max(8, n_rows * 0.6)
fig_width = max(14, n_cols * 1.6)
fig, ax = plt.subplots(figsize=(fig_width, fig_height))
ax.axis('tight')
ax.axis('off')
# 创建表格
table = ax.table(cellText=table_data,
colLabels=header,
cellLoc='center',
loc='center',
bbox=[0, 0, 1, 1])
table.auto_set_font_size(False)
table.set_fontsize(9)
table.scale(1, 2.2) # 增加行高,便于居中
# 设置表头样式
for j in range(n_cols):
table[(0, j)].set_facecolor('#F4B084')
table[(0, j)].set_text_props(weight='bold', color='white')
# -----------------------------
# 🔧 实现“类别”列跨三行合并 & 垂直居中
# -----------------------------
if raw_data is not None:
i = 1 # 数据行索引(从表格第1行开始)
while i < n_rows:
row_type = raw_data[i - 1].get('row_type', '')
if row_type == 'category_start':
# 检查是否有后续两行属于同一类别
if i + 2 < n_rows:
# 获取这三行对应的原始数据类型
next1_type = raw_data[i].get('row_type', '')
next2_type = raw_data[i + 1].get('row_type', '')
if next1_type == 'category_middle' and next2_type == 'category_end':
# ✅ 可以合并这三行
# 清除第二、第三行的类别文本
table[(i + 1, 0)].set_text_props(text='')
table[(i + 2, 0)].set_text_props(text='')
# 设置统一背景色(浅灰)
for r in [i, i + 1, i + 2]:
table[(r, 0)].set_facecolor('#E6F3FF')
# 计算垂直居中位置:第 i+1 行(中间)
middle_row_idx = i + 1
category_name = raw_data[i - 1]['类别']
# 在中间行重新设置类别文本(覆盖默认值)
cell = table[(middle_row_idx, 0)]
cell._text.set_text(category_name)
cell._text.set_weight('bold')
cell._text.set_color('black')
# 可选:添加边框强调
for r in [i, i + 1, i + 2]:
table[(r, 0)].set_edgecolor('black')
table[(r, 0)].visible_edges = ['left', 'right', 'top', 'bottom']
# 跳过已处理的两行
i += 3
continue
elif row_type == 'total_start':
# 处理“总计”三行合并
if i + 2 < n_rows:
if (raw_data[i].get('row_type') == 'total_middle' and
raw_data[i + 1].get('row_type') == 'total_end'):
for r in [i, i + 1, i + 2]:
table[(r, 0)].set_facecolor('#FFFFCC')
table[(r, 0)]._text.set_text('')
middle_row_idx = i + 1
cell = table[(middle_row_idx, 0)]
cell._text.set_text("总计")
cell._text.set_weight('bold')
cell._text.set_color('red')
cell.set_facecolor('#FFFFCC')
i += 3
continue
i += 1
# -----------------------------
# 🔴 标红每列中“销售环比”的最低三项
# -----------------------------
sales_rows = []
for idx, row in enumerate(table_data):
if row[1] == '销售环比' and row[0] not in ['', '总计']: # 排除空和总计
sales_rows.append(idx)
for col_name in header:
if col_name in ['类别', '指标']: # 跳过非数值列
continue
col_idx = header.index(col_name)
values = []
for row_idx in sales_rows:
text = table_data[row_idx][col_idx]
try:
num = float(text.replace('%', '').replace('-', '').replace('+', ''))
if text.startswith('-'):
num = -num
values.append((row_idx, num))
except:
continue
# 排序取最小3个
sorted_vals = sorted(values, key=lambda x: x[1])
bottom3_row_indices = [x[0] for x in sorted_vals[:3]]
for row_idx in bottom3_row_indices:
table_cell = table[(row_idx + 1, col_idx)] # +1 因为有表头
table_cell._text.set_color('red')
table_cell._text.set_weight('bold')
# 设置标题
plt.title(title, fontsize=14, fontweight='bold', pad=40)
plt.tight_layout()
plt.savefig(output_path, dpi=300, bbox_inches='tight', facecolor='white')
plt.close()
print(f"✅ 图片生成成功: {output_path}")
return True
except Exception as e:
print(f"❌ 生成图片失败: {str(e)}")
import traceback
traceback.print_exc()
return False
def create_performance_report(path, df, categories, regions, report_type, region_name=None, raw_data=None):
"""创建绩效环比报表图片"""
try:
# 获取当前日期
now = dt.datetime.now()
date_str = now.strftime("%Y%m%d")
# 计算上周时间范围
yesterday = now - dt.timedelta(days=1)
last_week_start = (yesterday - dt.timedelta(days=yesterday.weekday() + 7)).strftime("%m月%d日")
last_week_end = (yesterday - dt.timedelta(days=yesterday.weekday() + 1)).strftime("%m月%d日")
this_week_start = (yesterday - dt.timedelta(days=yesterday.weekday())).strftime("%m月%d日")
this_week_end = yesterday.strftime("%m月%d日")
if report_type == 'region':
title = f"各大区各绩效类别环比对比表\n({last_week_start}-{last_week_end} vs {this_week_start}-{this_week_end})"
file_prefix = '大区绩效环比表'
else:
title = f"{region_name}各地市环比对比表\n({last_week_start}-{last_week_end} vs {this_week_start}-{this_week_end})"
file_prefix = f'{region_name}地市绩效环比表'
# 生成图片
file_mc = f'{file_prefix}_{date_str}'
output_path = os.path.join(path, f'{file_mc}.png')
success = create_table_image(df, title, output_path, categories, regions, raw_data)
if success:
print(f"图片生成成功: {output_path}")
return output_path
else:
return None
except Exception as e:
print(f"生成绩效环比报表失败: {str(e)}")
return None
def application_push_image(access_token, image_path, user_id="037565", agent_id="1000077"):
"""推送图片到企业微信(个人)"""
try:
# 上传图片获取media_id
with open(image_path, 'rb') as f:
files = {'media': f}
upload_url = f'https://qyapi.weixin.qq.com/cgi-bin/media/upload?access_token={access_token}&type=image'
upload_response = requests.post(upload_url, files=files).json()
if 'media_id' not in upload_response:
print(f"图片上传失败: {upload_response}")
return None
media_id = upload_response['media_id']
# 发送图片消息
send_url = f'https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token={access_token}'
payload = {
"touser": user_id,
"msgtype": "image",
"agentid": agent_id,
"image": {"media_id": media_id},
"safe": 0
}
response = requests.post(send_url, json=payload).json()
return response
except Exception as e:
print(f"图片发送失败: {str(e)}")
return None
def send_store_performance_report(path):
"""发送门店绩效环比报表"""
try:
# 初始化微信
wechat = Wechat('tXNMrgcTgeV3IAqJhWB7mOe_bcKe9EtdCDze_75mGeY')
access_token = wechat.access_token()
# 获取原始数据
sql = generate_store_performance_sql()
data, columns = oracle_connect(sql)
# 转换为DataFrame
df = pd.DataFrame(data, columns=columns)
print(f"获取到 {len(df)} 条原始数据")
# 数据验证
print("\n数据验证:")
print(f"大区列表: {sorted(df['大区'].unique())}")
print(f"地市列表: {sorted(df['地市'].unique())}")
print(f"类别列表: {sorted(df['类别'].unique())}")
image_paths = []
# 1. 生成各大区环比对比表(第一张图片)
print("\n" + "=" * 50)
print("生成各大区环比对比表")
print("=" * 50)
region_df, region_categories, region_list, region_raw_data = transform_data_for_region_comparison(df)
if region_df is not None and len(region_df) > 0:
region_image_path = create_performance_report(path, region_df, region_categories, region_list, 'region',
raw_data=region_raw_data)
if region_image_path:
image_paths.append(('各大区环比对比表', region_image_path))
# 2. 生成各大地市环比对比表(第2-5张图片)
regions = sorted(df['大区'].unique())
print(f"\n需要处理的大区: {regions}")
for region in regions:
print("\n" + "=" * 50)
print(f"生成 {region} 地市环比对比表")
print("=" * 50)
city_df, city_categories, city_list, city_raw_data = transform_data_for_city_comparison(df, region)
if city_df is not None and len(city_df) > 0:
# 将城市列表转换为显示用的区域列表
display_regions = city_list + [f'{region}合计']
city_image_path = create_performance_report(path, city_df, city_categories, display_regions, 'city',
region, raw_data=city_raw_data)
if city_image_path:
image_paths.append((f'{region}地市环比对比表', city_image_path))
# 推送所有报表图片给个人用户037565
for image_name, image_path in image_paths:
if os.path.exists(image_path):
# 只发送给个人用户037565
result = application_push_image(access_token, image_path, "037565")
if result and result.get('errcode') == 0:
print(f"{dt.datetime.now()} - {image_name} 个人推送成功")
else:
print(f"{dt.datetime.now()} - {image_name} 个人推送失败")
# 删除临时文件
os.remove(image_path)
return True
except Exception as e:
print(f"{dt.datetime.now()} - 门店绩效环比报表推送失败: {str(e)}")
return False
def run_store_performance_scheduler(path):
"""运行门店绩效环比报表定时任务"""
# 每天早上7:30执行
schedule.every().day.at("07:30").do(send_store_performance_report, path=path)
# 立即测试一次
print(f"{dt.datetime.now()} - 正在执行门店绩效环比报表首次测试...")
send_store_performance_report(path)
while True:
schedule.run_pending()
time.sleep(60)
if __name__ == '__main__':
print(f'门店绩效环比报表程序启动时间: {dt.datetime.now()}')
output_path = r'D:\门店绩效环比报表'
if not os.path.exists(output_path):
os.makedirs(output_path)
# 启动定时任务线程
scheduler_thread = Thread(target=run_store_performance_scheduler, args=(output_path,))
scheduler_thread.daemon = True
scheduler_thread.start()
try:
while True:
time.sleep(60)
except KeyboardInterrupt:
print("门店绩效环比报表程序已停止")
E:\Anaconda3-2024.02.1\python.exe E:\Pycharm-2023.3.4\project\pythonProject\venv\推送\1-部长绩效类别周一早推送.py
门店绩效环比报表程序启动时间: 2025-10-12 09:43:51.970665
2025-10-12 09:43:51.971662 - 正在执行门店绩效环比报表首次测试...
获取到 24499 条原始数据
数据验证:
大区列表: ['豫北大区', '豫南大区', '郑州东区', '郑州西区']
地市列表: ['三门峡地区', '信阳地区', '南阳地区', '周口地区', '商丘地区', '安阳地区', '平顶山地区', '开封地区', '新乡地区', '洛阳地区', '济源地区', '漯河地区', '濮阳地区', '焦作地区', '许昌地区', '郑东1区', '郑东2区', '郑东3区', '郑西1区', '郑西2区', '郑西3区', '驻马店地区', '鹤壁地区']
类别列表: ['A', 'A+', 'B', 'C', 'C+', 'D', 'D+', 'E', 'F', 'b', 'c', '未分类']
==================================================
生成各大区环比对比表
==================================================
原始数据行数: 24499
大区列表: ['豫北大区', '豫南大区', '郑州东区', '郑州西区']
类别列表: ['A', 'A+', 'B', 'C', 'C+', 'D', 'D+', 'E', 'F', 'b', 'c', '未分类']
大区对比表形状: (39, 7)
E:\Pycharm-2023.3.4\project\pythonProject\venv\推送\1-部长绩效类别周一早推送.py:338: UserWarning: Starting a Matplotlib GUI outside of the main thread will likely fail.
fig, ax = plt.subplots(figsize=(fig_width, fig_height))
❌ 生成图片失败: unhashable type: 'list'
Traceback (most recent call last):
File "E:\Pycharm-2023.3.4\project\pythonProject\venv\推送\1-部长绩效类别周一早推送.py", line 397, in create_table_image
table[(r, 0)].visible_edges = ['left', 'right', 'top', 'bottom']
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "E:\Anaconda3-2024.02.1\Lib\site-packages\matplotlib\table.py", line 209, in visible_edges
elif value in self._edge_aliases:
^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: unhashable type: 'list'
需要处理的大区: ['豫北大区', '豫南大区', '郑州东区', '郑州西区']
==================================================
生成 豫北大区 地市环比对比表
==================================================
处理大区 豫北大区, 数据行数: 7583
地市列表: ['三门峡地区', '商丘地区', '安阳地区', '开封地区', '新乡地区', '洛阳地区', '济源地区', '濮阳地区', '焦作地区', '鹤壁地区']
类别列表: ['A', 'A+', 'B', 'C', 'C+', 'D', 'D+', 'E', 'F', 'b', 'c', '未分类']
地市对比表形状: (39, 13)
E:\Pycharm-2023.3.4\project\pythonProject\venv\推送\1-部长绩效类别周一早推送.py:338: UserWarning: Starting a Matplotlib GUI outside of the main thread will likely fail.
fig, ax = plt.subplots(figsize=(fig_width, fig_height))
Traceback (most recent call last):
File "E:\Pycharm-2023.3.4\project\pythonProject\venv\推送\1-部长绩效类别周一早推送.py", line 397, in create_table_image
table[(r, 0)].visible_edges = ['left', 'right', 'top', 'bottom']
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "E:\Anaconda3-2024.02.1\Lib\site-packages\matplotlib\table.py", line 209, in visible_edges
elif value in self._edge_aliases:
^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: unhashable type: 'list'
❌ 生成图片失败: unhashable type: 'list'
==================================================
生成 豫南大区 地市环比对比表
==================================================
处理大区 豫南大区, 数据行数: 8132
地市列表: ['信阳地区', '南阳地区', '周口地区', '平顶山地区', '漯河地区', '许昌地区', '驻马店地区']
类别列表: ['A', 'A+', 'B', 'C', 'C+', 'D', 'D+', 'E', 'F', 'b', 'c', '未分类']
地市对比表形状: (39, 10)
E:\Pycharm-2023.3.4\project\pythonProject\venv\推送\1-部长绩效类别周一早推送.py:338: UserWarning: Starting a Matplotlib GUI outside of the main thread will likely fail.
fig, ax = plt.subplots(figsize=(fig_width, fig_height))
❌ 生成图片失败: unhashable type: 'list'
==================================================
生成 郑州东区 地市环比对比表
==================================================
处理大区 郑州东区, 数据行数: 4559
地市列表: ['郑东1区', '郑东2区', '郑东3区']
类别列表: ['A', 'A+', 'B', 'C', 'C+', 'D', 'D+', 'E', 'F', 'b', 'c', '未分类']
Traceback (most recent call last):
File "E:\Pycharm-2023.3.4\project\pythonProject\venv\推送\1-部长绩效类别周一早推送.py", line 397, in create_table_image
table[(r, 0)].visible_edges = ['left', 'right', 'top', 'bottom']
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "E:\Anaconda3-2024.02.1\Lib\site-packages\matplotlib\table.py", line 209, in visible_edges
elif value in self._edge_aliases:
^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: unhashable type: 'list'
地市对比表形状: (39, 6)
E:\Pycharm-2023.3.4\project\pythonProject\venv\推送\1-部长绩效类别周一早推送.py:338: UserWarning: Starting a Matplotlib GUI outside of the main thread will likely fail.
fig, ax = plt.subplots(figsize=(fig_width, fig_height))
Traceback (most recent call last):
File "E:\Pycharm-2023.3.4\project\pythonProject\venv\推送\1-部长绩效类别周一早推送.py", line 397, in create_table_image
table[(r, 0)].visible_edges = ['left', 'right', 'top', 'bottom']
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "E:\Anaconda3-2024.02.1\Lib\site-packages\matplotlib\table.py", line 209, in visible_edges
elif value in self._edge_aliases:
^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: unhashable type: 'list'
❌ 生成图片失败: unhashable type: 'list'
==================================================
生成 郑州西区 地市环比对比表
==================================================
处理大区 郑州西区, 数据行数: 4225
地市列表: ['郑西1区', '郑西2区', '郑西3区']
类别列表: ['A', 'A+', 'B', 'C', 'C+', 'D', 'D+', 'E', 'F', 'b', 'c', '未分类']
地市对比表形状: (39, 6)
E:\Pycharm-2023.3.4\project\pythonProject\venv\推送\1-部长绩效类别周一早推送.py:338: UserWarning: Starting a Matplotlib GUI outside of the main thread will likely fail.
fig, ax = plt.subplots(figsize=(fig_width, fig_height))
❌ 生成图片失败: unhashable type: 'list'
Traceback (most recent call last):
File "E:\Pycharm-2023.3.4\project\pythonProject\venv\推送\1-部长绩效类别周一早推送.py", line 397, in create_table_image
table[(r, 0)].visible_edges = ['left', 'right', 'top', 'bottom']
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "E:\Anaconda3-2024.02.1\Lib\site-packages\matplotlib\table.py", line 209, in visible_edges
elif value in self._edge_aliases:
^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: unhashable type: 'list'