![](/img/trans.png)
[英]How to loop through all sheets and if cells match copy range to sheet?
[英]Loop through all sheets, if cell=string, copy three cells to special sheet
我正在使用excel2007。我有一個發票系統,在其中輸入采購訂單編號,它會生成一個以po號為工作表名稱的新發票,並將其復制到同一工作表的單元格中,然后從那里它是手動填寫並保存的。 每個發票在單元格C6中具有十四種供應類型之一(例如,從下拉列表中選擇的打印供應或清潔供應)。 一切都很好。
我想跟蹤每種耗材類型花費了多少,因此我需要查看每張發票,檢查耗材類型並復制三個不連續的單元格(日期(A6:B6),po#(F6:G6)和金額(G39))到該供應類型的“支票簿樣式”表中的一行。
我猜偽代碼看起來像這樣:
這就是我簡單地遍歷所有工作表並復制單元格而未按供應類型對它們進行排序的原因-然后,我試圖使其僅使用打印發票而沒有成功。
Sub CopyRangeFromPrintingWorksheets()
Dim sh As Worksheet
Dim DestSh As Worksheet
Dim Last As Long
Dim CopyRng As Range
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
'Delete the sheet "Printing" if it exist
Application.DisplayAlerts = False
On Error Resume Next
ActiveWorkbook.Worksheets("Printing").Delete
On Error GoTo 0
Application.DisplayAlerts = True
'Add a worksheet with the name
Set DestSh = ActiveWorkbook.Worksheets.Add
DestSh.Name = "Printing"
'loop through all worksheets and copy the data to the DestSh
For Each sh In ActiveWorkbook.Worksheets
'If sh.Name <> DestSh.Name Then
If InStr(1, Worksheets(wks.Name).Range("C6:E6").Value, "Printing/Stationary 532-110", vbTextCompare) = 1 Then
' If LCase(Left(sh.Name, 4)) = "tly-" Then
'Find the last row with data on the DestSh
Last = LastRow(DestSh)
'Fill in the range that you want to copy
Set CopyRng = sh.Range("G3")
'Test if there enough rows in the DestSh to copy all the data
If Last + CopyRng.Rows.Count > DestSh.Rows.Count Then
MsgBox "There are not enough rows in the Destsh"
GoTo ExitTheSub
End If
'This copies values/formats, want to copy the
'values or want to copy everything
CopyRng.Copy
With DestSh.Cells(Last + 1, "B")
.PasteSpecial xlPasteValues
.PasteSpecial xlPasteFormats
Application.CutCopyMode = False
End With
'Optional: This will copy the sheet name in the A column
DestSh.Cells(Last + 1, "A").Resize(CopyRng.Rows.Count).Value = sh.Name
'Copy ordered by cell to column C
DestSh.Cells(Last + 1, "D").Resize(CopyRng.Rows.Count).Value = sh.Range("G39")
'Copy date cell to proper column
DestSh.Cells(Last + 1, "C").Resize(CopyRng.Rows.Count).Value = sh.Range("C6")
DestSh.Cells(Last + 1, "E").Resize(CopyRng.Rows.Count).Value = sh.Range("E8")
End If
Next
ExitTheSub:
Application.GoTo DestSh.Cells(1)
'AutoFit the column width in the DestSh sheet
DestSh.Columns.AutoFit
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
我什至研究了精選案例,但仍然沒有成功。 試圖錄制marco並毫無靈感地看那個代碼。 似乎應該沒有那么難...但是我不知道最實用的方法。 指向正確方向的指針太棒了!
有可能在VBA中解決此問題,但這將非常麻煩且脆弱。
這種方法的一個問題是您將數據存儲在多個位置,這些數據可能會不同步。 另外,您需要三種不同的數據視圖:
在Access或更嚴重的數據庫系統中,這樣做是微不足道的,但是稍加搜索使我相信,在Excel中,您可以得到以上兩個中的兩個,但不能同時獲得三個。 但是,以下鏈接可能會有所幫助:
您可以使用3-d引用對數據求和,但是我認為您不能從3-d引用(對於支票簿樣式的視圖)創建數據透視表:
您還可以將多個工作表合並到數據透視表中,但是看起來源數據必須已經處於支票簿樣式的視圖中,因此無法獲取數據的單發票視圖:
底線:如果您有時間專門解決此問題,建議將解決方案移至Access。
我得出的結論與phoog相同,但方向不同。 下面,我仔細研究了您的代碼,提出了一些更改建議,但是我很難相信您可以完成這項工作。
點1
您是否打開了多個工作簿? 在運行宏之前,您是否要在它們之間切換? 假設您打開了三個工作簿(A,B和C)。 同樣,假設此宏和發票在工作簿A中。如果在啟動宏時使用工作簿C,則C將為ActiveWorkBook。 可以跨多個工作簿運行宏,但是它增加了一定程度的復雜性,我相信您可以做到。 如果在啟動宏時僅打開一個工作簿,則不需要ActiveWorkbook.
。
點2
我不喜歡將On Error
用作可以避免的錯誤。 這可能並不重要,但是刪除某些內容然后重新創建它對我來說是錯誤的。 我會這樣做:
Dim DestSh as Worksheet
Dim Found As Boolean
Dim InxWS As Integer
Found = False
For InxWS = 1 To Worksheets.Count
If Worksheets(InxWS).Name = "Printing" Then
Found = True
' Use whichever of the following two statements is most appropriate
' This completely deletes the contents of the worksheet
Worksheets(InxWS).Cells.EntireRow.Delete
' This deletes the contents of the worksheet but keeps the column widths
Worksheets(InxWS).Cells.EntireRow.ClearContents
Exit For
End If
Next
If Not Found Then
Set DestSh = Worksheets.Add
DestSh.Name = "Printing"
End If
點3
我發現以下內容沒有問題:
For Each sh In Worksheets
If sh.Name <> DestSh.Name Then
End If
Next
For Each
來說,這是工作表中的一種非常好的方法。
您需要一些檢查您不檢查工作表“打印”的方法。 但是,如果目標工作表總是要“打印”,則可以寫sh.Name <> "Printing"
。
另一方面,如果我想炫耀,我會寫:
Const DestShName as String = "Printing"
: :
DestSh.Name = DestShName
: :
If sh.Name <> DestShName Then
使用此代碼,我可以通過更改Const(常量)語句來更改目標工作表的名稱。
點4
考慮:
Worksheets(wks.Name).Range("C6:E6").Value
什么是wks
? for變量是sh
?
我猜您沒有Option Explicit
作為模塊的第一行。 Option Explicit
說您要禁止使用未聲明的變量。
Worksheets(sh.Name)
與sh
相同。
我假設“ C6:E6”已合並。 如果需要合並區域的值,請使用左上方的單元格。 所以Range("C6").Value
。
您的精選案例將采用以下形式:
With sh
Select Case .Range("C6").Value
Case "Printing"
' Do something
Case "Cleaning"
' Do something
Case "Stationary"
' Do something
Case "Books"
: :
Case Else
' Do something about an unknown supply type
End Select
End With
點5
如果我理解正確,則您有14種耗材類型,每種類型都有其自己的目的地表。 在循環中,您將需要像這樣的Select Case
來准備目標表。 供應類型與工作表名稱相同嗎? 如果沒有,這將變得非常混亂,特別是如果您添加其他供應類型。
可能值得考慮數組。
Dim InxShST as Integer
Dim SheetNameList() as String
Dim SupplyTypeList() as String
SheetNameList = Array("Print", "Clean", "Stat", ... )
SupplyTypeList = Array("Printing supplies", "Cleaning supplies", ... )
使用相同的工作表名稱和供應類型,您可以在采購訂單中找到供應類型並將其轉換為工作表名稱。 如果添加新的供應類型,只需在每個數組的末尾添加一個新值。
回到第2點。我建議您忘記通過VBA添加工作表; 手動創建14張紙。
代碼變為:
For InxWS = 1 To Worksheets.Count
For InxShST = LBound(SheetNameList) To UBound(SheetNameList)
If Worksheets(InxWS).Name = SheetNameList(InxShST) Then
Worksheets(InxWS).Cells.EntireRow.ClearContents
Exit For
End If
Next
Next
我承認這比較復雜,但是它可以根據您的需要准備很多張紙。 您有兩個循環:一個用於工作表,一個用於工作表名稱。 當您找到火柴時,便有一張需要清除的紙。 LBound
代表下限。 UBound
代表上限。 第二個For-Loop
調整為數組的大小。
您可以使用:
For Each SheetNameCrnt In SheetNameList
這看起來可能更簡單。 但是,通過使用索引,可以將SheetNameList(InxShST)
與SupplyTypeList(InxShST)
其他要點
您確定要每個采購訂單一張工作表嗎? 您一天有多少個采購訂單。 10? 100? 500? 這可能是一個非常難以管理的工作簿。
根據宏中的其他語句,我假設您有一個固定的標頭,然后每個訂購的產品有一個數據行。 您沒有定義這些行的性質,但是我想您要將它們復制到適當的工作表中。
我也許可以猜測這些數據行的結構,但是我必須質疑您的設計。 如果我從您那里訂購了打印機墨盒和一些肥皂粉,是否需要兩份采購訂單? 我認為您不會贏得我的生意。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.