模板转换工具

import pandas as pd
import  os
from datetime import datetime
import re
import time
start_time = time.time()

"""
获取未导入的数据,且去除了没有电话号码,年龄小于60大于18
"""
# 初始化一个空的列表来存储所有的 DataFrame
dataframes = []
for root,dirs,files in os.walk('./data'):
    # 合并历史数据
    for data_path in files:
        data_path=os.path.join('./data',data_path)
        print(data_path)
        df = pd.read_excel(data_path)
        dataframes.append(df)
    print('合并历史数据')
# 使用 concat 函数将所有的 DataFrame 合并成一个总表
# ignore_index=True 表示重置索引,这样合并后的总表将有一个连续的索引
combined_df = pd.concat(dataframes, ignore_index=True)
print('合并完成')
# 保存合并后的总表到 Excel 文件
combined_df.to_excel('./dir/已经导入的数据.xlsx', index=False)
# combined_df=pd.read_excel('./dir/已经导入的数据.xlsx')

total_df=pd.read_excel('./客户信息.xlsx')
# total_df=pd.read_excel('./hh.xlsx')

# 筛选出满足条件的data
# 定义正则表达式模式
id_pattern = re.compile(r'^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$')

# 筛选符合格式的身份证号码
valid_ids = total_df['证件号'].str.match(id_pattern)

# 对符合格式的身份证号码计算年龄
def calculate_age_from_id(id_number):
    try:
        # 假设身份证号码是18位的,且出生日期位于第7到14位
        birth_date_str = id_number[6:14]
        # 将字符串转换为日期对象,注意这里我们假设输入的身份证号码是有效的
        birth_date = datetime.strptime(birth_date_str, '%Y%m%d')

        # 获取当前日期
        today = datetime.today()

        # 计算年龄
        age = today.year - birth_date.year - ((today.month, today.day) < (birth_date.month, birth_date.day))

        return age
    except ValueError as e:
        # 捕获日期格式错误或日期无效的情况
        print(f"{id_number}身份证号码中的出生日期无效或格式错误:{e}")
        return None

# 应用函数并创建新列存储年龄
total_df['age'] = total_df.loc[valid_ids, '证件号'].apply(calculate_age_from_id)
# 筛选年龄大于18岁且小于60岁的数据(只考虑有效身份证号码的行)
filtered_df = total_df.loc[valid_ids & (total_df['age'] > 18) & (total_df['age'] < 60)]
# 定义一个函数来检查字符串是否是有效的手机号码(以1开头,11位数字)
def is_valid_phone_number(phone):
    # 使用正则表达式来匹配有效的手机号码
    pattern = r'^1\d{10}$'
    return re.match(pattern, str(phone)) is not None if pd.notna(phone) else False


# 应用这个函数来创建一个布尔索引
valid_phone_mask = filtered_df['移动电话'].apply(is_valid_phone_number)

# 使用布尔索引来筛选出有有效手机号码的行(同时排除空值)
df_with_valid_phones = filtered_df[valid_phone_mask & filtered_df['移动电话'] != '']

# 使用布尔索引来筛选出有有效手机号码的行
df_with_valid_phones = df_with_valid_phones[valid_phone_mask]
df_with_valid_phones.to_excel('./dir/符合要求的数据.xlsx',index=False)

pd.set_option('display.float_format', lambda x: '%.0f' % x)

# 去掉已经导入的数据  根据姓名  客户号  年纪  身份证后四位
# 获取表 combined_df 表示 已经批量导入的 中的客户号     combined_df是历史数据
# customer_ids_B = combined_df['客户编号'].values
# # 筛选没有批量导入的数据   df_with_valid_phones是有效数据
# df_A_filtered = df_with_valid_phones[~df_with_valid_phones['客户号'].isin(customer_ids_B)]

combined_df['身份证号后四位'] = combined_df['证件号码'].str[-4:]
combined_df.rename(columns={'客户编号': '客户号', '客户名称': '姓名','年龄':'age'}, inplace=True)
df_with_valid_phones['身份证号后四位'] = df_with_valid_phones['证件号'].str[-4:]
df_with_valid_phones['客户号']=df_with_valid_phones['客户号'].astype(object)
combined_df['客户号']=combined_df['客户号'].astype(object)
merged_df = pd.merge(df_with_valid_phones, combined_df, on=['客户号', '姓名', 'age', '身份证号后四位'], how='left', suffixes=('_A', '_B'),
                     indicator=True)
# 我们使用indicator参数来标记每行数据的来源
# '_merge'列的值为'both'表示该记录在A表和B表中都存在
# 我们要保留的是'_merge'值为'left_only'的记录,即只存在于A表中的记录
df_A_filtered = merged_df[merged_df['_merge'] == 'left_only'][df_with_valid_phones.columns.tolist()]


df_A_filtered.to_excel('./未导入的数据.xlsx',index=False)


end_time = time.time()
elapsed_time = end_time - start_time
# 将秒转换为分钟和秒
minutes, seconds = divmod(elapsed_time, 60)
print(f"执行时间: {minutes:.2f} 分钟和 {seconds:.2f} 秒")

import pandas as pd
import  os
from datetime import datetime
import re
import numpy as np
import pandas as pd
from openpyxl import load_workbook
from openpyxl.utils.dataframe import dataframe_to_rows
from openpyxl.styles import NamedStyle

from openpyxl import load_workbook
from openpyxl.utils.dataframe import dataframe_to_rows
from openpyxl.styles import PatternFill, Border, Side, Alignment, Font
import time
start_time = time.time()

def append_dataframe_with_format( df,save_path, sheet_name=None, startrow=None):
    book = load_workbook('最新导入模板.xlsx')
    if sheet_name is None:
        sheet = book.active
    else:
        sheet = book[sheet_name]

    if startrow is None:
        startrow = sheet.max_row + 1

    # 假设我们复制第一行的格式作为新行的格式模板
    template_row = 10

    # 将DataFrame转换为行列表,并追加到工作表中
    for r_idx, row in enumerate(dataframe_to_rows(df, index=False, header=False), start=startrow):
        for c_idx, value in enumerate(row, start=1):
            # 获取模板单元格
            template_cell = sheet.cell(row=template_row, column=c_idx)

            # 创建新单元格并设置值
            new_cell = sheet.cell(row=r_idx, column=c_idx, value=value)

            # 复制格式属性
            if template_cell.has_style:
                # 字体
                if template_cell.font:
                    new_cell.font = template_cell.font.copy()
                # 填充
                if template_cell.fill:
                    new_cell.fill = template_cell.fill.copy()
                # 边框
                if template_cell.border:
                    new_border = Border(
                        top=Side(style=template_cell.border.top.style, color=template_cell.border.top.color),
                        bottom=Side(style=template_cell.border.bottom.style, color=template_cell.border.bottom.color),
                        left=Side(style=template_cell.border.left.style, color=template_cell.border.left.color),
                        right=Side(style=template_cell.border.right.style, color=template_cell.border.right.color)
                    )
                    new_cell.border = new_border
                # 对齐方式
                if template_cell.alignment:
                    new_cell.alignment = template_cell.alignment.copy()
                # 可以添加更多格式属性的复制逻辑,如数字格式等

    book.save(save_path)

# 定义函数来“添加”B表内容到A表
def add_b_to_a(B):
    """
    添加B到A中,并且保留A的格式
    """
    # 由于A表和B表没有直接匹配字段,我们假设所有B表的客户都是A表户主的新家庭成员
    # 我们将B表的每一行作为一个新行添加到A表的末尾,并填充相关信息

    # 创建一个新的DataFrame来存储合并后的数据
    C = pd.DataFrame()  # 保留A表的原始数据

    # 对于B表的每一行,创建一个新行添加到C表中
    for _, row_b in B.iterrows():
        new_row = {
    "序号":  C['序号'].max() + 1 if not C.empty else 1,  # 如果C表为空,则序号为1,否则为当前最大序号+1
    "户主名称*": row_b['姓名'],
    "户主证件类型*": "居民身份证",
    "户主证件号码*": row_b['证件号'],  # 这里应该是具体的证件号码,但出于隐私考虑,使用“手工输入”作为示例
    "客户细分类型*": "经营户",  # 假设选择的是经营户
    "与客户关系*": "本人",  # 假设是户主本人
    "成员名称*": row_b['姓名'],
    "证件类型*": "居民身份证",
    "证件号码*": row_b['证件号'],  # 同上
    "身份证地址": row_b['地址'],
    "是否三类人员": "否",  # 假设不是三类人员
    "联系电话": row_b['移动电话'],
    "户口簿户号": " ",
    "健康状况": "良好",  # 假设健康状况良好
    "婚姻状况": "已婚",  # 假设已婚
    "学历信息": "高中",  # 假设学历为大学本科
    "是否985、211院校以及双一流大学": "否",  # 假设不是985、211或双一流大学
    "工作单位": "务农",
    "主要收入类型": "农业收入",  # 假设主要收入类型为经营收入
    "职业信息": "农、林、牧、渔业生产及辅助人员",  # 假设职业为企事业单位负责人
    "经营地址": " ",
    "是否公职人员": "否",  # 假设不是公职人员
    "是否小微企业主": "否",  # 假设是小微企业主
    "是否个体工商户": "否",  # 假设不是个体工商户
    "是否农户": "否",  # 假设不是农户
    "是否家庭劳动力": "是",  # 假设是家庭劳动力
    "是否外出务工": "否",  # 假设没有外出务工
    "是否缴纳公积金": "是",  # 假设缴纳公积金
    "年平均工资(元)": '',  # 假设年平均工资为50000元
    "公积金缴存基数(元)": '',  # 假设公积金缴存基数为3000元
    "是否参加养老保险": "是",  # 假设参加养老保险
    "统一社会机构代码": "",  # 通常是企业的代码,个人不需要填写
    "是否有合法合规、手续齐全的经营项目,且经营一年以上": " ",  # 假设有合法合规的经营项目且经营一年以上
    "是否全款车辆为本次授信办理抵押登记": " ",  # 假设没有全款车辆用于抵押
    "车辆情况": " ",  # 假设没有车辆
    "车辆使用性质": "",  # 如果有车辆,这里会是车辆的使用性质,如家用、商用等
    "车辆是否抵押": "",  # 假设车辆没有抵押
    "是否有经营项目为运输业且行车证、驾驶证、挂靠协议等手续齐全": "否",  # 假设没有运输业经营项目
    "是否自有全款房产且为本次授信办理抵押登记增信": "否",  # 假设没有全款房产用于抵押
    "可以办理抵押登记的房产位置": " ",  # 如果有房产,这里会是房产的位置
    "房产面积(平方米)": 100,  # 假设房产面积为100平方米
    "房产建成年份": 2010,  # 假设房产建成年份为2010年
    "装修情况": "普通装修",  # 假设房产为普通装修
    "房产评估价值(元)": 500000,  # 假设房产评估价值为500000元
    "是否抵押": "否",  # 假设房产没有抵押
    "是否有自有房产剩余价值为本次授信办理再次抵押登记": "否",  # 假设没有房产剩余价值用于抵押
    "剩余价值(元)": '',  # 如果有剩余价值,这里会是具体的金额
    "不能办理抵押登记的房产类型": "小产权房",  # 如果有不能办理抵押登记的房产,这里会是房产的类型
    "房产面积(平方米)_不能抵押": 50,  # 假设不能抵押的房产面积为50平方米
    "房产建成年份_不能抵押": 2000,  # 假设不能抵押的房产建成年份为2000年
    "房屋结构_不能抵押": "砖混",  # 假设不能抵押的房产为砖混结构
    "全款结清但不能办理抵押登记的自有房产面积(平方米)": '',  # 假设没有全款结清但不能办理抵押登记的房产
    "全款结清但不能办理抵押登记的自有房产建成年份": '',  # 同上,没有则填0或空值
    "装修情况_不能抵押": "未装修/毛坯",  # 假设不能抵押的房产为未装修/毛坯
    "林权证明": "无",  # 假设没有林权证明
    "林权面积(亩)": 0,  # 如果没有林权,则面积为0
    "其他资产(名称)": "无",  # 假设没有其他资产
    "是否抵押_其他资产": "否",  # 假设其他资产没有抵押
    "数量_其他资产": 0,  # 如果没有其他资产,则数量为0
    "预估价值(元)_其他资产": 0,  # 如果没有其他资产,则预估价值为0
    "个人荣誉": "",  # 假设没有个人荣誉
    "家庭荣誉": "未知",  # 假设没有家庭荣誉
    "家庭及邻里关系": "和睦",  # 假设家庭及邻里关系和睦
    "支付宝芝麻信用评分": " ",  # 这里应该是具体的信用评分,但出于隐私考虑,使用“手工输入”作为示例
    "生产项目种类": "种植",  # 假设生产项目种类为种植
    "类型_生产项目": "其他",  # 如果有更具体的类型,则填写在这里
    "年营收规模": "10-20万",  # 假设年营收规模为10-20万
    "年收入(元)": 10000,  # 假设年收入为80000元
    "年支出(元)": '',  # 假设年支出为60000元
    "备注": " ",  # 如果有备注信息,则填写在这里
    "负债类型": " ",  # 假设负债类型为银行贷款
    "负债金额(元)": '',  # 假设负债金额为20000元
    "是否涉黄": "否",  # 假设没有涉黄
    "是否涉赌": "否",  # 假设没有涉赌
    "是否涉毒": "否",  # 假设没有涉毒
    "其他负面": "未知",  # 假设没有其他负面记录
    "近两年内在他行有不良征信记录次数": '',  # 假设近两年内没有不良征信记录
    "在其他金融机构(含互联网类贷款)已有信用类贷款额度(元)": '',  # 假设已有信用类贷款额度为10000元
    "在其他金融机构(含互联网类贷款)已有保证担保贷款额度(元)": '',  # 假设没有保证担保贷款额度
    "在其他金融机构(含互联网类贷款)已有抵质押贷款额度(元)": '',  # 假设没有抵质押贷款额度
    "在其他金融机构(含互联网类贷款)已有个人住房按揭贷款额度(元)": '',  # 假设已有个人住房按揭贷款额度为300000元
    "在其他金融机构(含互联网类贷款)已对外提供保证担保的贷款额度(元)": '',  # 假设没有对外提供保证担保的贷款额度
    "是否需要资金支持": "生产经营",  # 假设需要资金支持
    "需求金额(元)": ''  # 假设需求金额为100000元
}
        # C = C.append(new_row, ignore_index=True)
        new_row=pd.DataFrame([new_row])
        C=pd.concat([C, new_row], ignore_index=True)

    return C
def split_and_save_dataframe(df, max_rows_per_file, file_prefix, output_dir='.'):
    """
    将DataFrame分割成多个较小的DataFrame,并保存为独立的文件。

    参数:
    df (pd.DataFrame): 要分割的DataFrame。
    max_rows_per_file (int): 每个文件最多包含的行数。
    file_prefix (str): 输出文件的前缀名。
    output_dir (str): 输出文件的目录(默认为当前目录)。

    返回:
    None
    """
    # 确保输出目录存在
    output_dir=os.path.join(output_dir,str(key))
    os.makedirs(output_dir, exist_ok=True)

    # 计算需要多少个文件
    num_files = (len(df) // max_rows_per_file) + (1 if len(df) % max_rows_per_file != 0 else 0)

    # 循环分割并保存DataFrame
    for i in range(num_files):
        # 计算当前文件的起始和结束索引
        start_index = i * max_rows_per_file
        end_index = min((i + 1) * max_rows_per_file, len(df))

        # 切片创建小DataFrame
        small_df = df.iloc[start_index:end_index]

        # 构造文件名
        now = datetime.now()
        formatted_time_no_colons = now.strftime("%Y-%m-%d_%H_%M_%S")

        # 构建文件名(使用下划线替换冒号)
        file_name = f"{file_prefix}_{formatted_time_no_colons}_part_{i + 1}.xlsx"

        # 使用 os.path.join 将文件名与输出目录结合(但这里我们直接拼接,因为output_dir已经是原始字符串)
        # 注意:如果output_dir是用户输入的,应该使用os.path.join并确保它是正确的路径格式
        file_path = os.path.normpath(os.path.join(output_dir, file_name))
        #
        # file_name = f"{file_prefix}_part_{i + 1}.xlsx"
        # file_path = os.path.join(output_dir, file_name)

        # 保存小DataFrame为CSV文件并且保留格式
        small_df=add_b_to_a(small_df)
        append_dataframe_with_format(small_df,file_path)
        # small_df.to_excel(file_path, index=False)

        print(f"Saved {file_path} with {len(small_df)} rows.")


# 读入模板数据
df = pd.read_excel('./最新导入模板.xlsx',header=2)
# 读入未导入的数据
# n_df=pd.read_excel('./新建文件夹/未导入的数据.xlsx',nrows=10)
n_df=pd.read_excel('./未导入的数据.xlsx')

n_df['地址'] = n_df['地址'].astype(str).fillna('')
# 分别按照开户机构和地址进行分类
township_list = [
'hh'
]
n_df['township'] = pd.NA  # 使用pd.NA表示缺失值

# 遍历详细地址列,判断属于哪一个乡镇,并更新新列
for index, row in n_df.iterrows():
    detailed_address = row['地址']
    # 这里我们简单使用字符串包含关系来判断,实际情况中可能需要更复杂的匹配逻辑
    for township in township_list:
        if township in detailed_address:
            # 找到匹配,更新乡镇列
            n_df.at[index, 'township'] = township  # 假设乡镇名称是地址的最后一个部分
            # 注意:上面的split方法可能不适用于所有情况,你需要根据实际情况调整
            break  # 找到匹配后退出循环
# print(n_df)
grouped=n_df.groupby('township')
# 将分组转换为字典,键是地区的组合,值是对应的DataFrame
dict_of_dfs = {key: group for key, group in grouped}
# 如果你想遍历所有的DataFrame,你可以这样做:
print('按照地区分')
for key, df_in_group in dict_of_dfs.items():
    # df_in_group = add_b_to_a(df, df_in_group)
    split_and_save_dataframe(df_in_group, max_rows_per_file=2000, file_prefix=key, output_dir='./地区')
# 按照机构分
grouped = n_df.groupby('开户机构')
# print('按照机构分')
# # 将分组转换为字典,键是地区的组合,值是对应的DataFrame
# dict_of_dfs = {key: group for key, group in grouped}
# # 如果你想遍历所有的DataFrame,你可以这样做:
# for key, df_in_group in dict_of_dfs.items():
#     # df_in_group = add_b_to_a(df)
#     split_and_save_dataframe(df_in_group, max_rows_per_file=20, file_prefix=key, output_dir='./机构')
#
# n_df.to_excel('./hh.xlsx',index=False)

end_time = time.time()
elapsed_time = end_time - start_time
# 将秒转换为分钟和秒
minutes, seconds = divmod(elapsed_time, 60)
print(f"执行时间: {minutes:.2f} 分钟和 {seconds:.2f} 秒")

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一壶浊酒..

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值