一、前言

大家好,今天我来介绍一下我接的zhenguo老师的第一个Python单子。我完成这个单子前后不到2小时。
首先我接到这个单子的想法是处理Excel表,在两个表之间建立联系,并通过项目需求,修改excel表中的数据。我是运用面向过程写的,将每一步都放在了不同的函数中,下面让我来介绍一下我是怎么通过自己的思路一步一步完成的。
做完单子后,zhenguo老师很快就给我转账了,并且没有二次修改,感觉很省心:
投稿这篇文章后,zhenguo老师又给我50元稿费:

先上客户的需求

二、代码实现及讲解

  1. 模块的导入
主要用到的模块为openpyxl、random
import
 openpyxl

import
 random

from
  openpyxl.utils.cell 
import
 get_column_letter,column_index_from_string

除了运用到openpyxl和random还用到了openpyxl中的utils包下cell模块的两个方法,第一个方法get_column_letter的作用是将整型转换为对应excel中列属性的字符串,例如:12转换为L,50转换为AX
第二个方法是将字符串转换为整型,其本质类似于10进制和27进制之间的转换,当然你也可以自己写,下面附上自己写的行(整型)转换为列(字符串)的代码。
def num_to_string(n):

    column = n - 1

    real_colum = 
''
while
 column >= 26:

        value = column // 26

        column = column % 26

        real_colum += chr(value + 64)

    real_colum += chr(column + 65)

return
 real_colum

2.获取“数据原表”中数据
#创建一个全局变量MATERIAL_MESSAGE
MATERIAL_MESSAGE = []

#获取小宛中数据
def get_construct_message():

#读取数据原表.xlsx表
    wb = openpyxl.load_workbook(
'数据原表.xlsx'
)

#获取获取当前活动工作表,默认为第一个表
    ws = wb.active

#获取在生产记录更新.xlsx中的可以用到的数据存入MATERIAL_MESSAGE中
for
 row 
in
 range(1,ws.max_row + 1):

if
 ws[f
'A{row}'
].value == 
'日期'
:

for
 i 
in
 range(ord(
'B'
),ord(
'I'
)):

                material = []

#将日期转换为与生产记录更新中相对应写法的形式
                date = ws[f
'B{row}'
].value.translate(str.maketrans(
'年月'
,
'--'
))

                date = date.replace(
'号'
,
''
)

                material.append(date)

                i = chr(i)

                material.append(ws[f
'{i}{row + 1}'
].value)

                material.append(ws[f
'{i}{row + 3}'
].value)

                MATERIAL_MESSAGE.append(material)

print
(MATERIAL_MESSAGE)

3.获取生产记录更新表中的日期和材料
# 将客户要求的对应数据存入字典中
TABLES = {
"水泥"
:
"水泥1"
,
"粉煤灰"
:
"煤灰"
,
"河沙"
:
"沙1"
,
"粗骨料1"
:
"石1"
,
"粗骨料2"
:
"石2"
,
"减水剂"
:
"外加剂"
,
"水"
:
"水"
}

#存入生产记录更新表的日期和其所在的行数
DATE = []

#存入生产记录更新表的材料和其所在的列数
MATERIAL = []

wb = openpyxl.load_workbook(
'生产记录更新.xlsx'
)

ws = wb.active

#获取日期
def get_date():

for
 row 
in
 range(3,ws.max_row + 1):

#将日期进行分割合并转换成与MATERIAL_MESSAGE中对应日期的格式
        date = str(ws[f
'B{row}'
].value).split()[0]

        date_list = date.split(
'-'
)

if'0'in
 date_list[1]:

            date_list[1] = date_list[1].replace(
'0'
,
''
)

if'0'in
 date_list[2]:

            date_list[2] = date_list[2].replace(
'0'
,
''
)

        date = 
'-'
.join(date_list)

        DATE.append([date,row])

    pprint.pprint(DATE)


#获取材料
def get_material():

    n = 0

for
 column 
in
 ws[1]:

        n += 1

#判断该单元格的内容是否在TABLES中
if
 column.value 
in
 TABLES.values():

#运用行列转换的方法进行转换
            MATERIAL.append([column.value,get_column_letter(n - 1)])

    pprint.pprint(MATERIAL)

DATE表部分数据
MATERIAL表数据
4.对生产数据更新表中数据的修改
#两个参数分别为材料的类型和所在的列数
def update_default(matrial,letter):

for
 row 
in
 range(3,ws.max_row + 1):

#判断单元格是否为空
if
 ws[f
'{letter}{row}'
].value != None:

for
 i 
in
 range(len(MATERIAL_MESSAGE)):

#需求条件,要将连个表中的日期和材料类型进行一一对应
if
 DATE[row-3][0] == MATERIAL_MESSAGE[i][0] and matrial == TABLES[MATERIAL_MESSAGE[i][1]]:

#修改形参letter对应列的每个符号要求的单元格对应的设定值
                    ws[f
'{letter}{DATE[row - 3][1]}'
].value = MATERIAL_MESSAGE[i][2]

#分别获取该列列号的下两列对应的列号
                    letter_random = get_column_letter(column_index_from_string(letter) + 2)

                    letter_real = get_column_letter(column_index_from_string(letter) + 1)

#判断该列是否在这三列中,若在其中则得到-2到2之间的随机数,否则-1到1之间的随机数,并更新误差值
if
 letter 
in
 (
'AV'
,
'BB'
,
'BE'
):

                        ws[f
'{letter_random}{DATE[row - 3][1]}'
].value = round(random.uniform(-2, 2), 1)

else
:

                        ws[f
'{letter_random}{DATE[row - 3][1]}'
].value = round(random.uniform(-1, 1), 1)

#运用设定值和误差值更新中间的实际值
                    ws[f
'{letter_real}{DATE[row - 3][1]}'
].value = round(ws[f
'{letter}{DATE[row - 3][1]}'
].value * (1 + ws[f
'{letter_random}{DATE[row - 3][1]}'
].value * 0.01),2)


5.最后,调用函数并保存数据
def main():


    get_construct_message()

    get_date()

    get_material()

for
 i 
in
 MATERIAL:

        update_default(i[0],i[1])

    wb.save(
'生产记录更新.xlsx'
)



if
 __name__ == 
"__main__"
:

    main()

三、效果展示

修改前部分数据
修改后部分数据

四、结尾

通过自己的的两个小时的努力奋战完成了这个单子,总的来说,难度不在于怎么修改数据,而是在于怎么把两个表相互关联,通过这次接单让我对excel表能够更加熟练地进行操作,接单既能提升自己的能力,又能赚点外快,何乐而不为呢?
继续阅读
阅读原文