合并文件内容,请大神给个代码
excel吧
全部回复
仅看楼主
level 12
lvcha青青 楼主
刚才发了个网盘链接,好像帖子给吞了。
需求说明:
将N个此文件中的内容复制到一薄一表中,第1、2、3行为标题行,内容一样,只复制一次,其他的不要标题行与最后一行内容。
最右侧数据到BU列
第1、2行为合并单元格,最后一行也是合并单元格,系统导出的就是这样。
2022年05月05日 02点05分 1
level 12
lvcha青青 楼主
2022年05月05日 02点05分 2
level 11
如果没有几个文件先手工打开再另存为xlsx文件,然后估计2个for走一圈就解决了。
文件如果很多可以用workbooks.open(filename) 方法打开文件,用getobjct(filename) 就你这问题肯定不行的。
如果open打开也有问题,那打开后用do加个1s的延时去findwindow弹出窗口句柄,如果失败说明正常运行,否则枚举此句柄下的command句柄,包含有“Y”就sendmessage 一个click参数过去就可以了,后面的窗口操作方法相同(自己查一下相关API函数的使用方法)。
导出数据是是否有选项,比如文件类型可为csv或者xlsx的,xls太古老了。
2022年05月05日 05点05分 3
WPS里有一个合并表格的功能,对于XLSX的可以正常合并,但对于这个XLS文件就无能为力了,原先我都是先把原表另存为XLSX以后再用WPS去合并。好几十个文件,全部另存一下也比较费事。
2022年05月05日 06点05分
@lvcha青青 可以随机提供2个xls文件,我按猫老大的方法测试一下。
2022年05月05日 06点05分
level 11
'瞎子又在审核 [滑稽]
2022年05月05日 05点05分 4
原文件不经修改,一旦公开,最轻的可能就是有人请我去喝茶了。
2022年05月05日 06点05分
可以用Application.DisplayAlerts = False 忽略打开文件时的错误提示.
2022年05月05日 05点05分
@zipall 倒是没想过用这开关,楼主没有提供源文件,如果这方法可行那后面直接按条件汇总就可以了 [真棒]
2022年05月05日 06点05分
@🌴菠萝蜜🌴 原文件因为一旦修改之后,再打开就会丢失文件无法打开,在示例文件里的下面那个图片就是了。如果不修改的话,涉及一些保密内容,不便公开。
2022年05月05日 06点05分
level 7
方方格子[滑稽]
2022年05月05日 07点05分 5
具体操作呢
2022年05月05日 07点05分
level 12
lvcha青青 楼主
这要是有难度的话,能不能做到将一个文件夹内的所有XLS文件另存为XLSX格式,并且删除前3行与最后一行内容?
2022年05月05日 07点05分 6
@提亲风成 这个链接里34M的可执行程序是个啥东东?下载完了,没敢运行啊。
2022年05月05日 11点05分
@lvcha青青 用python做的合并工具
2022年05月05日 11点05分
@提亲风成 将文件放在文件夹里面,将会跳过前两行和最后一行,将合并后的文件保存到c盘合并了.xlsx
2022年05月05日 11点05分
@提亲风成 为何你们链接显示正常运行我的总是说的“网页链接”?
2022年05月05日 12点05分
level 11
hi,这是我用百度网盘分享的内容~复制这段内容打开「百度网盘」APP即可获取
链接:网页链接
提取码:rqbv
2022年05月05日 12点05分 7
运行代码试试看,我特意选的打开时显示格式不符的
2022年05月05日 12点05分
level 11
链接: 网页链接 提取码: rqbv 复制这段内容后打开百度网盘手机App,操作更方便哦
2022年05月05日 12点05分 8
你这是手机贴的吗?我在电脑上贴链接正常。
2022年05月05日 12点05分
@lvcha青青 手机贴的,你试试看,把你的文件放到那个《原始数据》文件夹里面,再运行代码,会新生成一个带时间的新工作簿
2022年05月05日 13点05分
level 11
'在当前目录新建一个xlsm文件并复制代码到模块,关闭当前目录中的所有xls文件(否则open时会有问题,未做error处理)
'随机测试了几个xls文件正常,你这文件我就搞不清楚了。源数据在当前工作簿的当前表格中
Option Explicit
Sub abc()
 Dim a, f, n, m, p, w, pth
 Call doevent(False)
 pth = ThisWorkbook.Path & "\"
 f = Dir(pth & "*.*")
 Do While Len(f) > 0
  If LCase(Right(f, 4)) = ".xls" And Left(f, 1) <> "~" Then 'xls文件且非临时文件
    Set w = Workbooks.Open(pth & f)
    With w
    With .ActiveSheet
     a = .[a1].CurrentRegion.Value
     If IsArray(a) Then '当前表格有数据区
      m = m + 1
      If m = 1 Then
       .[a1].Resize(UBound(a) - 1, UBound(a, 2)).Copy _
        ThisWorkbook.ActiveSheet.[a1]
      Else
       p = ThisWorkbook.ActiveSheet.Cells(Rows.Count, "a").End(xlUp).Row + 1
       .[a1].Offset(3).Resize(UBound(a) - 4, UBound(a, 2)).Copy _
        ThisWorkbook.ActiveSheet.Cells(p, "a")
      End If
     Else
      Debug.Print pth & f
     End If
    End With
    .Close False
    End With
  End If
  f = Dir
 Loop
 Call doevent(True)
End Sub
Function doevent(flag As Boolean)
 With Application
  .DisplayAlerts = flag
  .ScreenUpdating = flag
 End With
End Function
2022年05月05日 13点05分 9
代码测试后,能够正常提取到所有数据行内容,且保留唯一的3行标题行。瑕疵有二,1是,合并的数据中有合计行,仅有一行,可能是与标题行等同处理了。2是,合并的数据顺序不是并不是按文件名的顺序。虽然有两点小瑕疵,但瑕不掩瑜。不愧对是简单问题复杂化,但复杂问题简单化的VBA大佬。
2022年05月05日 14点05分
提到提取内容中有合计行的内容,是因为,虽然仅仅只有一行合计,正常情况下,这个不是问题,但是,它不是在提取后数据的最后一行,在数据的中间[黑线]
2022年05月05日 15点05分
@lvcha青青 是猫老大一锤定音,一个开关就解决了你的问题。
2022年05月05日 23点05分
@lvcha青青 汇总类的问题如果条件明确都是非常简单的。
2022年05月05日 23点05分
level 11
'出现第一种情况是因为源数据有问题,如果最后一行没有合并行那么数据将会丢失,已修改
'排序需要规则,文件名按py升序处理,你也可以改成按asc升序来排序,或者抓图上规则再修改
Option Explicit
Sub abc()
 Dim a, i, f, n, m, p, w, pth, filename(1 To 10 ^ 4, 1 To 3), cnt
 pth = ThisWorkbook.Path
 If Not getfilename(filename, cnt, pth, ".xls") Then MsgBox "!": Exit Sub
 Call bsort(filename, 1, cnt, 1, 3, 3) '默认按文件名py升序,可改成asc或提供规则自定义
 Call doevent(False)
 For i = 1 To cnt
  Set w = Workbooks.Open(filename(i, 1))
  With w
   With .ActiveSheet
    a = .[a1].CurrentRegion.Value
    If IsArray(a) Then '当前表格有数据区
     m = m + 1
     If m = 1 Then '包括标题
      .[a1].Resize(UBound(a), UBound(a, 2)).Copy _
       ThisWorkbook.ActiveSheet.[a1]
     Else '去除前3行标题
      p = ThisWorkbook.ActiveSheet.Cells(Rows.Count, "a").End(xlUp).Row + 1
      .[a1].Offset(3).Resize(UBound(a) - 3, UBound(a, 2)).Copy _
       ThisWorkbook.ActiveSheet.Cells(p, "a")
     End If
    Else
     Debug.Print filename(i, 1) '如果有输出说明这个问题数据有问题,打开确认一下
    End If
   End With
   .Close False
  End With
 Next
 For i = Cells(Rows.Count, "a").End(xlUp).Row To 4 Step -1 '删除合计行
  If InStr(Cells(i, "a"), "合计行") > 0 Then Rows(i).Delete
 Next
 Call doevent(True)
End Sub
Function getfilename(filename, cnt, pth, mark) As Boolean
 Dim f
 If right(pth, 1) <> "\" Then pth = pth & "\"
 f = Dir(pth & "*.*")
 Do While Len(f) > 0
  If LCase(right(f, Len(mark))) = LCase(mark) Then
   If left(f, 1) <> "~" Then
    cnt = cnt + 1
    filename(cnt, 1) = pth & f
    filename(cnt, 2) = LCase(f)
    filename(cnt, 3) = LCase(left(f, Len(f) - Len(mark)))
   End If
  End If
  f = Dir
 Loop
 If cnt > 0 Then getfilename = True
End Function
Function bsort(a, first, last, left, right, key)
 Dim i, j, k, t
 For i = first To last - 1
  For j = first To last + first - 1 - i
   If StrComp(a(j, key), a(j + 1, key), vbTextCompare) = 1 Then 'by py
   'If a(j, key) > a(j + 1, key) Then 'by asc
    For k = left To right
     t = a(j, k): a(j, k) = a(j + 1, k): a(j + 1, k) = t
    Next
   End If
 Next j, i
End Function
Function doevent(flag As Boolean)
 With Application
  .DisplayAlerts = flag
  .ScreenUpdating = flag
 End With
End Function
2022年05月05日 23点05分 10
这个代码在测试之后发现,依旧有一个合计行在数据中间。并且数据行少了两行。之前那个代码虽然有合并行,但是数据行不缺。我把文件命名发到下面,大神看看还有救吗?
2022年05月05日 23点05分
level 12
lvcha青青 楼主
才注意到每个文件的最下方有两行合并单元格,会不会是因为这个的原因,才导致提取的数据中间有一个合计行?
2022年05月06日 00点05分 11
level 12
lvcha青青 楼主
Export_10010002[1_5000].xls
Export_10010002[10001_15000].xls
Export_10010002[15001_20000].xls
Export_10010002[20001_25000].xls
Export_10010002[25001_30000].xls
Export_10010002[30001_35000].xls
Export_10010002[35001_40000].xls
Export_10010002[40001_45000].xls
Export_10010002[45001_48126].xls
Export_10010002[5001_10000].xls
2022年05月06日 00点05分 12
level 11
'按文件名命名规则做了升序,随机测试了一下汇总数据都没有问题。
'源文件"合计"标志必须在A列,缺少源文件就猜到这里了。
Option Explicit
Sub abc()
 Dim a, i, f, n, m, p, w, pth, filename(1 To 10 ^ 4, 1 To 3), cnt
 pth = ThisWorkbook.Path
 If Not getfilename(filename, cnt, pth, ".xls") Then MsgBox "!": Exit Sub
 Call doevent(False)
 Cells.ClearContents
 For i = 1 To cnt
  Set w = Workbooks.Open(filename(i, 1))
  With w
   With .ActiveSheet
    a = .[a1].CurrentRegion.Value
    If IsArray(a) Then
     m = m + 1
     If m = 1 Then
      .[a1].Resize(UBound(a), UBound(a, 2)).Copy _
       ThisWorkbook.ActiveSheet.[a1]
     Else
      p = ThisWorkbook.ActiveSheet.Cells(Rows.Count, "a").End(xlUp).Row + 1
      .[a1].Offset(3).Resize(UBound(a) - 3, UBound(a, 2)).Copy _
       ThisWorkbook.ActiveSheet.Cells(p, "a")
     End If
    Else
     Debug.Print filename(i, 1)
    End If
   End With
   .Close False
  End With
 Next
 For i = Cells(Rows.Count, "a").End(xlUp).Row To 4 Step -1
  If InStr(Cells(i, "a").Value, "合计") > 0 Then Rows(i).Delete
 Next
 Call doevent(True)
End Sub
Function getfilename(filename, cnt, pth, mark) As Boolean
 Dim f, i, t, p
 If right(pth, 1) <> "\" Then pth = pth & "\"
 f = Dir(pth & "*.*")
 Do While Len(f) > 0
  If LCase(right(f, Len(mark))) = LCase(mark) Then
   If left(f, 1) <> "~" Then
    cnt = cnt + 1
    filename(cnt, 1) = pth & f
    If InStr(f, "[") Then
     t = Split(f, "[")
     filename(cnt, 2) = t(0)
     If InStr(t(1), "_") Then
      t = Split(t(1), "_")
      If IsNumeric(t(0)) Then
       filename(cnt, 3) = Val(t(0))
      Else
       MsgBox pth & f: End
      End If
     Else
      MsgBox pth & f: End
     End If
    Else
     MsgBox pth & f: End
    End If
   End If
  End If
  f = Dir
 Loop
 If cnt > 0 Then
  Call bsort(filename, 1, cnt, 1, 3, 2)
  For i = 1 To cnt
   If filename(i, 2) <> filename(i + 1, 2) Then
    Call bsort(filename, p + 1, i, 1, 3, 3)
    p = i
   End If
  Next
  getfilename = True
 End If
End Function
Function bsort(a, first, last, left, right, key)
 Dim i, j, k, t
 For i = first To last - 1
  For j = first To last + first - 1 - i
   If a(j, key) > a(j + 1, key) Then
    For k = left To right
     t = a(j, k): a(j, k) = a(j + 1, k): a(j + 1, k) = t
    Next
   End If
 Next j, i
End Function
Function doevent(flag As Boolean)
 With Application
  .DisplayAlerts = flag
  .ScreenUpdating = flag
 End With
End Function
2022年05月06日 03点05分 13
大神,数据都正确的按顺序提取出来了,但是楼上我贴的那图中,合计行下面的制表人那一行分别出现在了数据当中。辛苦大神能不能把这个完善一下,目前就差这一点了。
2022年05月06日 07点05分
我把 If InStr(Cells(i, "a").Value, "合计") > 0 Then Rows(i).Delete,中的合计改成制表人,加在后,再次合并数据,完美了。十分感谢VBA大佬。
2022年05月06日 07点05分
@lvcha青青 搞定了就可以 [汗]
2022年05月06日 07点05分
1