分享

如何批量提取多个工作簿固定位置数据?

 VBA说 2020-04-19
本篇文章说一个VBA常见应用案例,批量提取工作簿中特定位置数据。作为VBA入门的学习练手的案例非常合适。搞明白搞懂,汇总工作簿之类的问题都不在话下。

→案例需求:

首先,我有一堆待提取的表(每个表里分为加工总表和成本表):


汇总表和分表的数据对应关系如下:

加工总表:

/双击查看大图

成本表:

/双击查看大图

思路分析:

①批量提取必定要循环打开工作簿,再找到相对应位置直接取数据。让代码代替手工去循环打开工作簿。这里我们用GetOpenFilename方法,允许使用者选择需要汇总的工作簿路径,获取之后,对GetOpenFilename方法返回的路径进行循环。具体用法可以看历史文章:获取文件全路径(一)GetOpenFilename方法

②有一个稍微难一些的地方,成本表中需要提取的数据行数位置不固定


有的朋友可能想到用end属性,但是这里面有合并单元格,而且提取数据的周围上下都有数据,这些都是阻挡正确提取数据的地方。
这个时候就要找另外一些突破点:发现需要提取的数据都是位于【总计】这个单元格的附近。这样的话,我们就可以用Find函数查找【总计】这个单元格所在的位置,找到了他,提取他周围的单元格内容就简单多了。Find函数具体用法,详见历史文章:不得不说的高效Boy:Find方法

我觉得VBA入门的差别就在这了:会不会找规律,并将这些规律转化为代码的逻辑条件。

代码详解:

Sub 汇总清空之前的数据()
'//弹出窗口,让用户选择需要合并的工作簿
pth = Application.GetOpenFilename("文件(*.xls*),*.xls*", , "请选择文件", , True) 'GetOpenFilename支持通配符,true代表允许多选。
If Not IsArray(pth) Then '如果用户没有选择文件,则返回False,不是数组。
MsgBox "请选择需要汇总的工作簿"
Exit Sub '退出过程
End If
'//
Application.ScreenUpdating = False '禁止刷新,防止屏幕闪烁,提高运行速度
Application.AskToUpdateLinks = False '禁止提示更新链接
Application.DisplayAlerts = False '禁止无关的提示信息
Set thissht = ThisWorkbook.ActiveSheet '把代码工作簿的活动工作表赋值给对象变量thissht
thissht.Range("a2:k10000").ClearContents '清空除标题行以外的原有数据
For i = 1 To UBound(pth) 'GetOpenFilename多选文件的话返回的是一个数组,里面存放的是每个文件的路径,循环数组获取里面的文件路径。
Set wb = Workbooks.Open(pth(i)) '将打开的工作簿赋值给对象变量wb
Set sumsht = wb.Worksheets("加工总表") '将打开的工作簿的【加工总表】sheet赋值给对象变量sumsht
Set chengbensht = wb.Worksheets("成本表") '将打开的工作簿的【成本表】sheet赋值给对象变量sumsht
lastrow = thissht.Cells(thissht.Rows.Count, 1).End(3).Row + 1 '获取代码工作簿已使用的最大行号+1
With thissht 'with结构,简化代码
.Cells(lastrow, 1) = i '序号
.Cells(lastrow, 2) = sumsht.Range("a4") '加工任务
.Cells(lastrow, 3) = sumsht.Range("b4") '材料
.Cells(lastrow, 4) = sumsht.Range("c4") '厚度
.Cells(lastrow, 5) = sumsht.Range("e4") '加工时间
.Cells(lastrow, 6) = sumsht.Range("f4") '零件总数
Set zongji = chengbensht.UsedRange.Find("总计", , xlValues, xlWhole, xlByColumns, xlNext, True, True) 'find方法,查找【总计】关键字所在单元格
.Cells(lastrow, 7) = chengbensht.Cells(zongji.Row, 5) '和【总计】单元格同一行,第5列的数据就是所需要的穿孔个数
.Cells(lastrow, 8) = Replace(chengbensht.Cells(zongji.Row + 1, 5), "元/个", "") '在【总计】单元格下一行,第5列的数据就是所需要的单价
.Cells(lastrow, 9) = chengbensht.Cells(zongji.Row, 6) '理解同上
.Cells(lastrow, 10) = Replace(chengbensht.Cells(zongji.Row + 1, 6), "元/m", "") '理解同上
.Cells(lastrow, 11) = Replace(chengbensht.Cells(zongji.Row + 2, 5), "元", "") '理解同上
'上述几句可以用offset实现。
End With
wb.Close False '关闭打开的工作簿,直接用对象变量wb.clsoe即可。false表示不保存。
Next
Application.ScreenUpdating = True '开启刷新
Application.AskToUpdateLinks = True '开启提示更新链接
Application.DisplayAlerts = True '开启无关的提示信息
MsgBox "完成!"
End Sub
上述查找到【总计】单元格的位置之后,还可以用offset方法找到周围的单元格,这个可以自己试着写一下。

写在最后:

很多人说VBA怎么入门,迟迟不能入门,也有一些人迟迟摇摆不定到底学不学VBA,恐怕多刚学会VBA就被废弃了。


▪是否值得学
我想说的是,担心太多余了,技多不压身,学习VBA给你带来的效率回报,可能是你自己都想不到的。VBA,用了都说好。


▪关于迟迟不能入门
第一个是知识点的积累比如文中说的Find方法,你没学过这个,根本想不到当行数不确定的时候怎么获取。所以,一定的知识点积累是必要的。百度、问人或者刷教程都可以。

第二个是一定要敲代码:就算抄一遍也会有很多收获,因为你可能抄都抄不对。我刚开始入门的时候,自己写代码。表示单元格的Cells到底加不加s都会有疑问,Worksheets都拼不对。

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多