Board logo

標題: [發問] Excel VBA篩選處理資料加速問題 [打印本頁]

作者: wwwlen2002    時間: 2016-11-3 18:03     標題: Excel VBA篩選處理資料加速問題

各位大大好,小弟剛使用VBA不久,目前只會打簡單的function搭配錄製巨集

現在遇到的問題是,目前用迴圈讀檔,然後篩選後刪除不要的資訊
處理的資料是每天720個XML檔,每個檔案約莫900筆的資料 (一天約六十萬筆資料)
然而處理前幾個XML檔很快,但到後來就會越來越慢ex兩小時只跑了約540個檔案

現在的想法是可能是隨著資料變多篩選跟刪除的速度都會變慢
或許可以將篩選的結果貼至新工作表能增快速度,但貼至新工作表後不知如何自動選取適當的位置貼上(不要覆蓋現有資料繼續往下貼)

希望各位大大們能給予指教與幫助,感激不盡!

附上現在的VBA code與相關資料 rar檔

Sub test()
    '匯入xml檔_靜態
    ActiveWorkbook.XmlImport URL:= _
        "C:\Users\JM-ASUSCG5285\Desktop\CMS\20150101\cms_info_0000.xml", ImportMap:= _
        Nothing, Overwrite:=True, Destination:=Range("$A$1")
    ActiveWorkbook.XmlMaps("XML_Head_Map").Name = "XML_Head_Map_Info"
   
    Sheets("工作表2").Select
   '匯入xml檔_動態
    ActiveWorkbook.XmlImport URL:= _
        "C:\Users\JM-ASUSCG5285\Desktop\CMS\20150101\cms_value_0000.xml", ImportMap:= _
        Nothing, Overwrite:=True, Destination:=Range("$A$1")
    '刪除不需欄位
    Columns("A:B").Select
    Selection.Delete Shift:=xlToLeft
    Columns("B:B").Select
    Selection.Delete Shift:=xlToLeft
    Columns("C:C").Select
    Selection.Delete Shift:=xlToLeft
   
    With ActiveWorkbook.XmlMaps("XML_Head_Map")
        .ShowImportExportValidationErrors = False
        .AdjustColumnWidth = True
        .PreserveColumnFilter = True
        .PreserveNumberFormatting = True
        .AppendOnImport = True
    End With

    Range("D2").Select
    ActiveCell.FormulaR1C1 = "=ASC([@message])"
    Columns("D:D").ColumnWidth = 41
    Range("表格2[[#Headers],[欄1]]").Select
    ActiveCell.FormulaR1C1 = "全形轉半形"
   
    Range("E2").Select
    ActiveCell.FormulaR1C1 = _
        "=IF(COUNTIF([@message],""*壅塞*"")+COUNTIF([@message],""*K*"")+COUNTIF([@message],""*k*"")+COUNTIF([@message],""*雨*"")+COUNTIF([@message],""*天候不佳*""),1,0)"
    ActiveSheet.ListObjects("表格2").Range.AutoFilter Field:=5, Criteria1:="0"
    Rows("2:500000").Select
    Selection.Delete Shift:=xlUp
    ActiveSheet.ListObjects("表格2").Range.AutoFilter Field:=5
    Range("表格2[[#Headers],[欄1]]").Select
    ActiveCell.FormulaR1C1 = "含關鍵字與否"
    Columns("F:F").ColumnWidth = 17


        
    sPath = "C:\Users\JM-ASUSCG5285\Desktop\CMS\20150101\"
    sFile = Dir(sPath & "*.xml")
    'MsgBox (sFile)
    Dim i As Integer
    i = 1
    Do While sFile <> ""
        
        If sFile <> "cms_info_0000.xml" And sFile <> "cms_value_0000.xml" Then
                ActiveWorkbook.XmlMaps("XML_Head_Map").Import URL:= _
            sPath & sFile
            '動態處理
                ActiveSheet.ListObjects("表格2").Range.AutoFilter Field:=5, Criteria1:="0"
                Rows("2:500000").Select
                Selection.Delete Shift:=xlUp
                ActiveSheet.ListObjects("表格2").Range.AutoFilter Field:=5

        End If
        sFile = Dir()
        i = i + 1
       Loop
End Sub

   
原始資料部分檔   
[attach]25714[/attach]
作者: wwwlen2002    時間: 2016-11-8 16:12

  1. Sub 巨集1()

  2.     ' Timing
  3.     Dim Time0#
  4.     Time0 = Timer
  5.    
  6.     ' Close screenupdating to boost the procedure
  7.     Application.ScreenUpdating = False
  8.    
  9.     ' Import XML data (cms_info)
  10.     ActiveWorkbook.XmlImport URL:= _
  11.         "C:\Users\JM-ASUSCG5285\Desktop\CMS\20150101\cms_info_0000.xml", ImportMap:= _
  12.         Nothing, Overwrite:=True, Destination:=Range("$A$1")
  13.     ActiveWorkbook.XmlMaps("XML_Head_Map").Name = "XML_Head_Map_Info"
  14.    
  15.     ' Import another XML data (cms_value)
  16.     Sheets("工作表2").Select
  17.    
  18.     ActiveWorkbook.XmlImport URL:= _
  19.         "C:\Users\JM-ASUSCG5285\Desktop\CMS\20150101\cms_value_0000.xml", ImportMap:= _
  20.         Nothing, Overwrite:=True, Destination:=Range("$A$1")
  21.    
  22.     ' Delete unnecessary data
  23.     Columns("A:B").EntireColumn.Delete
  24.     Columns("B:B").EntireColumn.Delete
  25.     Columns("C:C").EntireColumn.Delete

  26.     ' Setting the succeeding import default
  27.     With ActiveWorkbook.XmlMaps("XML_Head_Map")
  28.         .ShowImportExportValidationErrors = False
  29.         .AdjustColumnWidth = True
  30.         .PreserveColumnFilter = True
  31.         .PreserveNumberFormatting = True
  32.         .AppendOnImport = False
  33.     End With

  34.     ' Deal with the string
  35.     [D1].FormulaR1C1 = "全形轉半形"
  36.     [D2].FormulaR1C1 = "=ASC([@message])"
  37.     Columns("D:D").ColumnWidth = 41
  38.    
  39.     [E1].FormulaR1C1 = "含關鍵字與否"
  40.     [E2].FormulaR1C1 = _
  41.         "=IF(COUNTIF([@message],""*壅塞*"")+COUNTIF([@message],""*K*"")+COUNTIF([@message],""*k*"")+COUNTIF([@message],""*雨*"")+COUNTIF([@message],""*天候不佳*""),1,0)"
  42.    
  43.     ' Find dest
  44.     'Dim dest&, count&
  45.     Count = 1
  46.     [F2].FormulaR1C1 = "=SUM([含關鍵字與否])"
  47.     Count = [F2].Value
  48.     Columns("F:F").EntireColumn.Delete
  49.     dest = Count + 1
  50.     'MsgBox (dest)
  51.     ' Filter
  52.     Dim i&, LR&
  53.     'dest = [F1].Value
  54.     'MsgBox (dest)
  55.     Sheets("工作表2").ListObjects("表格2").Range.AutoFilter Field:=5, Criteria1:="1"
  56.     LR = Range("A" & Rows.Count).End(xlUp).Row
  57.     Range("A1:P" & LR).SpecialCells(xlCellTypeVisible).Select
  58.     Selection.Copy
  59.     Sheets("工作表3").Range("A1").PasteSpecial xlPasteValues

  60.     Sheets("工作表2").ListObjects("表格2").Range.AutoFilter Field:=5

  61.     sPath = "C:\Users\JM-ASUSCG5285\Desktop\CMS\20150101\"
  62.     sFile = Dir(sPath & "*.xml")
  63.     'MsgBox (sFile)

  64.     i = 1
  65.     Do While sFile <> ""
  66.         If sFile <> "cms_info_0000.xml" And sFile <> "cms_value_0000.xml" Then
  67.                 ActiveWorkbook.XmlMaps("XML_Head_Map").Import URL:= _
  68.             sPath & sFile
  69.             If [A3].Value <> "" Then
  70.             '動態處理
  71.                 [F2].FormulaR1C1 = "=SUM([含關鍵字與否])"
  72.                 Count = [F2].Value
  73.                 Columns("F:F").EntireColumn.Delete
  74.                 dest = dest + 1
  75.                 Sheets("工作表2").ListObjects("表格2").Range.AutoFilter Field:=5, Criteria1:="1"
  76.                 LR = Range("A" & Rows.Count).End(xlUp).Row
  77.                 Range("A2:P" & LR).SpecialCells(xlCellTypeVisible).Select
  78.                 Selection.Copy
  79.                 Sheets("工作表3").Range("A" & dest).PasteSpecial xlPasteValues
  80.                 dest = dest + Count - 1
  81.                 Sheets("工作表2").ListObjects("表格2").Range.AutoFilter Field:=5
  82.             End If
  83.         End If
  84.         sFile = Dir()
  85.         i = i + 1
  86.     Loop
  87.    
  88.     ' Parameterize/ Structure the sheet
  89.     Sheets("工作表3").Select
  90.     ActiveSheet.ListObjects.Add(xlSrcRange, Range("$A$1:$E$" & dest), , xlYes).Name = "表格3"
  91.    
  92.     Application.ScreenUpdating = True
  93.     MsgBox "執行時間 " & Timer - Time0 & " 秒", vbOKOnly

  94. End Sub
複製代碼
爬了一些增進效率的文後
關掉screenupdating以及減少selection的使用
加上將匯入資料篩選想要資料後貼至新表格,而非在原表格篩選出不要資料刪除
速度快了非常多,約 1分半內跑完一整天的資料

目前遇到的問題是selection後的value想用transfer而非copy和paste的方式不知道怎麼處理
雖然不知道速度會再快多少,但目前結果算差強人意了
與大家分享,若有建議還請不吝提出,謝謝!
作者: stillfish00    時間: 2016-11-9 17:17

本帖最後由 stillfish00 於 2016-11-9 17:20 編輯

回復 2# wwwlen2002
只處理cms_value_####.xml
XML_PATH 自行改為正確路徑
參考 :
  1. Sub Test()
  2.     Dim t: t = Timer
  3.    
  4.     Const XML_PATH = "C:\Users\xxxxx\Downloads\CMS\CMS\20150101"
  5.     Dim oXml As Object: Set oXml = CreateObject("msxml2.domdocument")   
  6.     Dim sFile As String, sTime As String, sCmsid As String, sMessage As String
  7.     Dim oNodes As Object, arData, cnt As Long
  8.     ReDim arData(1 To 3, 1 To 1)
  9.     sFile = Dir(XML_PATH & "\")
  10.     Do While Len(sFile) > 0
  11.         If sFile Like "cms_value_####.xml" Then
  12.             oXml.Load XML_PATH & "\" & sFile
  13.             With oXml.ChildNodes(1)
  14.                 sTime = .getAttribute("updatetime")
  15.                 Set oNodes = .getElementsbyTagName("Info")
  16.                 ReDim Preserve arData(1 To 3, 1 To UBound(arData, 2) + oNodes.Length)
  17.                 For Each x In oNodes
  18.                     sMessage = WorksheetFunction.Asc(x.getAttribute("message"))   '全形轉半形
  19.                     If HasMyKeyWords(sMessage) Then
  20.                         sCmsid = x.getAttribute("cmsid")
  21.                         cnt = cnt + 1
  22.                         arData(1, cnt) = sTime
  23.                         arData(2, cnt) = sCmsid
  24.                         arData(3, cnt) = sMessage
  25.                     End If
  26.                 Next
  27.                 ReDim Preserve arData(1 To 3, 1 To cnt)
  28.             End With
  29.         End If
  30.         sFile = Dir()
  31.     Loop   
  32.    
  33.     If cnt > 0 Then
  34.         With Sheets.Add(After:=Sheets(Sheets.Count))
  35.             .[a1].Resize(1, 3) = Array("updatetime", "cmsid", "message")
  36.             .[a2].Resize(cnt, 3) = Application.Transpose(arData)
  37.             .UsedRange.Columns.AutoFit
  38.         End With
  39.     End If
  40.    
  41.     MsgBox "執行時間 " & Timer - t & " 秒", vbOKOnly
  42. End Sub

  43. Function HasMyKeyWords(s As String) As Boolean
  44.     For Each x In Array("壅塞", "K", "k", "雨", "天候不佳")
  45.         If InStr(1, s, x) > 0 Then
  46.             HasMyKeyWords = True
  47.             Exit Function
  48.         End If
  49.     Next
  50.     HasMyKeyWords = False
  51. End Function
複製代碼





歡迎光臨 麻辣家族討論版版 (http://forum.twbts.com/)