本内容以网上获取某电商公司的一段销售数据进行分析
Excel和VBA篇
首先用Excel打开表格,格式如下,总共一万多行,记录的是月销售记录,所有销售记录个表格格式都是一致的,因此,用VBA可以大大简化流程,减少复制和粘贴还有计算工作。
接下来打开VBA编辑器
Sub 调整类型()
Dim irow, a, sht, sht1, sht2, sht3
Dim arr() '定义需要的变量和数组
Set sht = Application.ActiveSheet '将当前活动的表格赋给变量sht
With sht '对当前的表格进行操作
If .Range("b2") = "" Then '处理1-6行表头,判断b2单元格是否为空
If .Range("n8") = "shipping credits" Then '如果n8单元格是某个值
Rows("1:7").Select '选中1到7行,并将其删除
Application.CutCopyMode = False
Selection.Delete Shift:=xlUp '后面的列左移
Else '如果n8单元格不是某个值
Rows("1:6").Select '选中1到6行,并将其删除
Application.CutCopyMode = False
Selection.Delete Shift:=xlUp
End If
End If 'if函数的逻辑判断,在VBA比在Excel表格里面输入函数,来的更加灵活,更好理解
If .Range("n1") = "shipping credits" Then '判断n1单元格是否为某个值
.Columns("Q:R").Select '如果是,则删除两列
Selection.Delete Shift:=xlToLeft
End If
' 最后创建需要汇总和计算的单元格
.Range("c1") = "类型"
.Range("v1") = "产品名称"
.Range("w1") = "公司SKU"
.Range("g1") = "数量"
End With
如此,表格的表头处理完成,如果是一次性操作,直接用鼠标点击可以完成,如果表格数量多,且每个月都要做这个工作,则可以一劳永逸。
接下来,如果想调整英文换成中文,也可以用查找替换,比如我想将c列单元格里面的order全部替换成订单
irow = Range("a65536").End(xlUp).Row 'a单元格的最后一行赋值给变量
Range("c1:c" & irow).Select '选中c1到c(此表格最后一行),此方法非常重要,可以判断当前表格某列最后一个单元格的行数
'将Order改为订单,同理有其他的也可以改
Selection.Replace What:="Order", Replacement:="订单", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
arr = Range("a1:u" & irow) '将此表格的内容存放在数组里面,可以大大提高运行速度
'接下来将需要匹配的表格赋值给变量
Set sht1 = Workbooks("参数核对表.xlsx").Sheets("SKU汇总")
Set sht2 = Workbooks("参数核对表.xlsx").Sheets("产品明细总表")
For i = 2 To irow '建立一个循环,从第2行执行到(有多少行执行多少行)
'判断是否是空值,并建立匹配sku和明细,Excel函数VLookup需要在前面加Application.WorksheetFunction
If arr(i, 5) <> "" Then '注意在数值里面arr(i, 5),表示第i行,第5列
Range("w" & i) = Application.WorksheetFunction.VLookup(arr(i, 5), sht1.[A:C], 3, 0)
Range("v" & i) = Application.WorksheetFunction.VLookup(arr(i, 5), sht1.[A:C], 2, 0)
End If
Next
'将表格执行完成之后,释放变量
Set sht = Nothing
Set sht1 = Nothing
Set sht2 = Nothing
Set sht3 = Nothing
End Sub
将文件夹里面的所有工作簿(workbook)里面的工作表(worksheet)合并到一个工作表里面
Sub wjhb()
Dim str As String
Dim wb As Workbook
Dim sht As Worksheet
str = Dir("E:\x\y\z\*.xls*")
For i = 1 To 100
Set wb = Workbooks.Open("E:\x\y\z\" & str)
For Each sht In wb.Sheets
If sht.Name = "订单汇总表" Then
sht.Copy after:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count)
ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count).Name = Left(wb.Name, 8) & sht.Name
End If
Next
wb.Close
str = Dir
If str = "" Then
Exit For
End If
Next
End Sub
将一个工作簿里面的所有工作表的内容全部复制到一个表里面
Sub shishi()
Dim sht1, sht
Set sht = Sheets("数据")
For Each sht1 In Sheets
If sht1.Name <> "数据" Then
sht1.Select
irow = Range("a65536").End(xlUp).Row
Range("a2:k" & irow).Select
Selection.Copy
sht.Select
a = Range("a65536").End(xlUp).Row
Range("a" & a + 1).Select '复制到B2单元格
ActiveSheet.Paste
b = Range("b65536").End(xlUp).Row
For i = a + 1 To b
Range("l" & i) = Right(Left(sht1.Name, 8), 2)
Next
End If
Next
Set sht = Nothing
End Sub
总结VBA里面的常用方法
1、Set sht = Application.ActiveSheet 将当前活动的表格赋给变量
2、With End With 语句,针对某一个对象做的所有操作
3、 If Elseif else 语句,逻辑判断,如果xx 则xx , 再如果xx 则xx,否则,xx
4、 .Select 选中某个对象(可以是表格,单元格,或者一行一列,或者是一块区域)
5、Rows("1:6") Columns("Q:R") 分别代表1-6行和QR两列
6、 .Delete 删除某个对象
7、irow = Range("a65536").End(xlUp).Row a列的最后一行的行数赋值给变量
irow = ActiveSheet.UsedRange.Rows.Count 这个表格的最后有数据的一行的行数赋值给变量
两种方法有区别,一个是针对某一列,一个是针对表格
8、Selection.Replace What:="xx", Replacement:="yy", 对选中的区域将xx替换成yy
9、For i = x To y 建立一个循环,从x循环到y
For Each sht In wb.Sheets 建立一个循环,遍历每个工作表
10、Application.WorksheetFunction.VLookup Excel函数前面加Application.WorksheetFunction
11、arr = Range("a1:y" & irow) 将区域赋值给数组
12、Set sht = Nothing 释放变量
13、Sheets.Add after:=Sheets(Sheets.Count) 新建一个表格在所有表格的后面
Sheets(Sheets.Count).Name = "xx" 让新建的表格名字等于xx
14、.Copy .Paste 复制和粘贴
15、 ActiveSheet.Range(" ").RemoveDuplicates Columns:=2, Header:=xlYes
将某个区域的重复项删除
16、Range(" ").Select Selection.Merge 对选中的区域合并单元格
最后墙裂推荐王佩丰老师的EXCEL和VBA视频教程,在网易云课堂搜索“王佩丰”即可
磨刀不误砍柴工
几行代码即可解决一个上午简单重复的工作
Python和pandas篇
import pandas as pd #导入相应的需要匹配的数据,设置好格式
df_product_sku = pd.read_excel("/Users/mac/desktop/参数核对表.xlsx", sheet_name="SKU汇总")
df_product_sku.columns = ["sku", "产品名称", "公司sku"] #重新设置列名
df_product_details = pd.read_excel("/Users/mac/desktop/参数核对表.xlsx", sheet_name="产品明细总表")
df_product_details1 = df_product_details[["综合SKU","成本元"]] #只有sku和成本的两列
df_product_details1.columns = ["公司sku", "成本单价"]
df_product_details2 = df_product_details[["综合SKU","UK8"]] #只有sku和运费的两列
df_product_details2.columns = ["公司sku","物流单价"]
df_product_self = pd.read_excel("/Users/mac/desktop/参数核对表.xlsx", sheet_name="自发货汇总")
df_product_self = df_product_self[["订单号", "计费"]]
df_product_self.columns = ["订单号", "物流单价"]
df1 = pd.read_excel("/Users/mac/desktop/DS-UK.xls")
a = 0 #命名一个变量为汇率
b = [] #设置一个空的列表
# 处理表头,如果是美国则删除Q R列 删除0到6行
if df1.iloc[5, 13] == "shipping credits": #iloc[5, 13]定位5行13列的单元格
df1 = df1.drop([16, 17], axis=1) #drop([16, 17], axis=1) 删除16,17列
b = list(range(0, 6))
#drop(b).reset_index(drop=True) 删除1-6行,重新设置索引,并且不增加新的列
df1 = df1.drop(b).reset_index(drop=True)
else:
b = list(range(0, 5))
df1 = df1.drop(b).reset_index(drop=True)
df1.columns = df1.iloc[0] #选取第一行作为列名
df1 = df1.drop([0]).reset_index(drop=True) #删除第一行
list_columns = list(df1.columns) 将列名取出来成为数组
list_columns[2] = "类型"
list_columns[6] = "数量"
list_columns[8] = "订单类型"
list_columns[3] = "订单号"
if list_columns[13] == "shipping credits":
list_columns[12] = "售价美元"
list_columns[-1] = "合计美元"
a = 6.5
elif list_columns[13] == "postage credits":
list_columns[12] = "售价英镑"
list_columns[-1] = "合计英镑"
a = 8.5
else:
list_columns[12] = "售价欧元"
list_columns[-1] = "合计欧元"
a = 7.5
df1.columns = list_columns #将表的列名改为列表
dict1 = {'Bestellung': "订单", 'Servicegebühr': '服务费', #调整类型
'übertrag': '转账', 'Versand durch Amazon Lagergebühr': '仓储费', 'Erstattung': '退货',
'Erstattung durch Rückbuchung': '退货', 'Anpassung': '调货','Blitzangebotsgebühr': '活动费',
'Commande': "订单", 'Frais de service': '服务费', 'Transfert': '转账', #调整法国的类型
'Frais de stock Expédié par Amazon': '仓储费', 'Remboursement': '退货',
'Ajustement': '调货','Tarif de la Vente Flash': '活动费',
'Pedido': "订单", 'Tarifa de prestación de servicio': '服务费', 'Transferir': '转账', #调整西班牙的类型
'Tarifas de inventario de Logística de Amazon': '仓储费', 'Reembolso': '退货',
'Ajuste': '调货','Tarif de la Vente Flash': '活动费',
'Ordine': "订单", 'Commissione di servizio': '服务费', 'Trasferimento': '转账', #调整意大利的类型
'Costo di stoccaggio Logistica di Amazon': '仓储费', 'Rimborso': '退货',
'Modifica': '调货','Tarif de la Vente Flash': '活动费',
'Order': "订单", 'Service Fee': '服务费', 'Transfer': '转账', #调整英美的类型
'Refund_Retrocharge': '仓储费', 'FBA Inventory Fee': '仓储费', 'Refund': '退货',
'Adjustment': '调货','Tarif de la Vente Flash': '活动费',
'Debt': 'FBA补贴','Lightning Deal Fee': '活动费'}
# 遍历字典循环,并且将表格的整列替换
for key,value in dict1.items():
df1.loc[df1["类型"]==key, "类型"] = value #筛选类型这一列中等于key的单元格
df1.fillna("", inplace=True) #用空值替换所有NAN的值,并且不创新新的表格
df1['类型'].replace("", "产品销毁费", inplace=True) #替换类型里面空值为产品销毁费
df1 = df1.merge(df_product_sku, on="sku", how="left") #匹配亚马逊SKU到公司的SKU,增加产品名称
df_t_sku = df1[df1["公司sku"].isnull()==False] #匹配到有sku的
df_no_sku = df1[df1["公司sku"].isna()==True] #没有匹配到sku的
df_t_sku_nrefund = df_t_sku[df_t_sku["类型"] != "退货"] # 类型不是退货的
df_t_sku_refund = df_t_sku[df_t_sku["类型"] == "退货"] # 类型是退货的
df_t_sku_nrefund = df_t_sku_nrefund.merge(df_product_details1, on="公司sku", how="left") #匹配非退货的成本
df_t_sku_refund = df_t_sku_refund.merge(df_product_details1, on="公司sku", how="left") #匹配退货的成本
df_t_sku_refund["成本单价"] = df_t_sku_refund["成本单价"] * -1 #退货的成本乘以-1
df_t_sku_nrefund["成本合计"] = df_t_sku_nrefund["成本单价"] * df_t_sku_nrefund["数量"]
df_t_sku_refund["成本合计"] = df_t_sku_refund["成本单价"] * df_t_sku_refund["数量"]
df_t_sku_nself = df_t_sku_nrefund[(df_t_sku_nrefund["订单类型"]=="") | \
(df_t_sku_nrefund["订单类型"]=="Amazon")] #订单非自发货
df_t_sku_self = df_t_sku_nrefund[(df_t_sku_nrefund["订单类型"]!="") & \
(df_t_sku_nrefund["订单类型"]!="Amazon")] #订单自发货
df_t_sku_rnself = df_t_sku_refund[(df_t_sku_refund["订单类型"]=="") | \
(df_t_sku_refund["订单类型"]=="Amazon")] #退货非自发货
df_t_sku_rself = df_t_sku_refund[(df_t_sku_refund["订单类型"]!="") & \
(df_t_sku_refund["订单类型"]!="Amazon")] #退货自发货
df_t_sku_nself = df_t_sku_nself.merge(df_product_details2, on="公司sku", how="left") #订单非自发货的运费
df_t_sku_rnself = df_t_sku_rnself.merge(df_product_details2, on="公司sku", how="left") #退货非自发货的运费
df_t_sku_rnself["物流单价"] = df_t_sku_rnself["物流单价"] * -1 #退货的物流单价乘以-1
df_t_sku_self = df_t_sku_self.merge(df_product_self, on="订单号", how="left") #订单自发货的运费
df_t_sku_rself = df_t_sku_rself.merge(df_product_self, on="订单号", how="left") #退货自发货的运费
df_t_sku_rself["物流单价"] = df_t_sku_rself["物流单价"] * -1 #退货的物流单价乘以-1
def total_logistics(x): 定义一个函数
x["物流合计"] = x["物流单价"] * x["数量"]
total_logistics(df_t_sku_nself)
total_logistics(df_t_sku_rnself)
df_t_sku_self["物流合计"] = df_t_sku_self["物流单价"]
df_t_sku_rself["物流合计"] = df_t_sku_rself["物流单价"]
df_total = df_t_sku_nself.append([df_t_sku_rnself, df_no_sku, df_t_sku_self, df_t_sku_rself], \
ignore_index=True, sort=False)
#df_t_sku_nself[df_t_sku_nself['订单号'].duplicated(keep='first')]# 找出重复项
df_total.fillna(float(0), inplace=True) #用0.00替换所有NAN的值
df_total["回款合计"] = df_total["合计英镑"] * a
df_total["销售合计"] = df_total["售价英镑"] * a
df_total["毛利"] = df_total.apply(lambda x: x["回款合计"] - x["物流合计"] - x["成本合计"], axis=1)
import numpy as np
#将数量这一列转换为浮点数
df_total["数量"] = df_total["数量"].apply(pd.to_numeric, errors='ignore') / 1
#以'类型', '产品名称', '公司sku'聚合 求"售价英镑", "合计英镑", "成本合计", '物流合计','数量'的合计
df2 = df_total.groupby(['类型', '产品名称', '公司sku'])\
[["售价英镑", "合计英镑", "成本合计", '物流合计','数量']].sum()
#append拼接两个表格 sort=False重新设置index
df3 = df2.loc["订单"].append(df2.loc["调货"], sort=False)
df4 = df3.groupby(['产品名称', '公司sku'])\
[["售价英镑", "合计英镑", "成本合计", '物流合计','数量']].sum()
df4 = df4.reset_index()
#df4.loc['合计'] = df4[["售价英镑", "合计英镑", "成本合计", '物流合计','数量']].apply(lambda x: x.sum())
df5 = df2.loc["退货"].reset_index() #对列进行重新排序
df6 = df2.loc[["产品销毁费", "仓储费", "服务费", "活动费"]].reset_index()
df4["类型"] = "订单"
df5["类型"] = "退货"
df_total_1 = df4.append([df5, df6], ignore_index=True, sort=False)
s = df_total_1["类型"]
df_total_1.drop(labels=['类型'], axis=1,inplace = True)
df_total_1.insert(0, '类型', s)
df_total_1.loc['合计'] = df_total_1[["售价英镑", "合计英镑", "成本合计", '物流合计','数量']].apply(lambda x: x.sum())
print(df_total_1)
总结python、pandas里面的常用方法
读取工作簿里面的某个工作表
pd.read_excel("/Users/mac/desktop/ .xlsx", sheet_name="")
设置表格的列名
df.columns = [" "]
删除x 和y 列
df = df.drop([x, y], axis=1)
删除表格里面b(0-4)行,并且重新设置索引
b = list(range(0, 5))
df = df.drop(b).reset_index(drop=True)
选取行列和单元格的操作
*loc方法*
#行
df.loc['6'] # 行名称为6的行
df.loc['5':'7'] # 行名称为5至7的行,注意是前闭后闭
df.loc[['5', '7']] # 行名称为5和7的行
#列
df.loc[:, 'B'] # 列名称为'B‘的列
df.loc[:, 'A':'C'] # 列名称为A至C的列,注意是前闭后闭
df.loc[:, ['A', 'C']] # 列名称为A和C的列
#块
df.loc['5':'7', 'A':'C'] # 行名称为5至7,列名称为A~C的一块数据
df.loc[['5', '7'], ['A', 'C']] # 行名称为5和7,列名称为A和C的一块数据
df.loc['5':'7', ['A', 'C']] # 行名称5至7,列名称A和C的一块数据
df.loc[['5', '7'], 'A':'C'] # 行名称为5和7,列名称为A~C的一块数据
#单元格
df.loc['5', 'A'] # 行名称为5,列名称为A的单元格数据
df.at['5', 'A'] # 同loc但速度快点
*iloc方法*
#行
df.iloc[1] # 第2行
df.iloc[0:3] # 前3行
df.iloc[[0, 3]] # 第1第4行
#列
df.iloc[:, 1] # 第2列
df.iloc[:, 0:3] # 前3列
df.iloc[:, [0, 3]] # 第1第4列
#块
df.iloc[0:3, 0:3] # 前3行,前3列的一块数据
df.iloc[[0, 3], [0, 3]] # 第1第4行,第1第4列的一块数据
df.iloc[0:3, [0, 3]] # 前3行,第1第4列的一块数据
df.iloc[[0, 3], 0:3] # 第1第4行,前3列的一块数据
#单元格
df.iloc[1, 1] # 第1行,第1列的单元格
df.iat[1, 1] # 同iloc但速度快点
总的来说,loc方法针对名称,iloc方法针对行列所在的位置,都是先行后列
替换表格里面的值
df.dropna(axis=0, how='any') # 行里有缺失值就丢掉,如果行里所有值是缺失值才丢掉可以how='all' axis=0对行操作
df.dropna(axis=1, how='any') # 列里有缺失值就丢掉 axis=1对列操作
df.fillna("", inplace=True) #用空值替换所有NAN的值
df['x'].replace("", ",", inplace=True) #用逗号替换x列的所有的空值
匹配和查找,merge类似VLOOKUP
df = df.merge(df1, on="x", how="left") #df和df1两个表格以x列匹配,按照df的x列进行匹配
选择某列不为空的值
df[df["x"].isna()==True] #x列非空的所有数据
多条件筛选
df = df[(df["x"]=="") | (df["y"]==1)] #表中x列等于空值,或者y列等于1的所有数据
df = df[(df["x"]> 8) & (df["y"]<= 6 )] #表中x列大于8,且y列小于等于6的所有数据
# |类似or &类似and
改变列的格式 apply方法,将函数施加给对象
df["x"] = df["x"].apply(pd.to_numeric, errors='ignore')#将x列转换为数字
创建透视表
df = df.pivot_table(values=["x", "y"],index=['a'], columns=['b'], aggfunc=[np.sum], margins=True)
#a为行,b为列,将x列和y列进行求和,并且有合计项的透视表