2015-03-30 66 views
-1

我被困在傳輸數據到彙總表中。我有兩張紙,想把它總結到第三張紙上。Consilidating和從多個工作表傳輸數據

       Sheet A 

     A    B     C     D 
1     Apple    Orange    Peach 
2 Period  Apple_Price  Orange_price   peach_price 
3  1   5      5     3     
4  2   6      4     9 
5  3   7           7 

           Sheet B 

     A    B     C     D 
1     Apple    Orange    Peach 
2 Period  Apple_weight  Orange_Weight   peach_Weight 
3  1   2.1      2.5     3.1     
4  2   2.1      1.1     2.1 
5  3   3.1           2.5 




       Summary sheet or sheet c (expected) 

     A    B     C     D 
1    Period     Price    Weight    
2 Apple   1      5     2.1 
3     2      6     2.1 
4     3      7     3.1 
5 Orange   1      5     2.5 
6     2      4     1.1 
7 Peach   1      3     3.1 
8     2      9     2.1 
9     3      7     2.5 

我已經開始寫代碼是有點像

For Each Name In Range("B1:D1") 
' To copy each name in to first column of summary 
Name.Cells.value.copy Worksheets("Summary").Offset(2,0) 
' Now to copy a column from each sheet in front of corresponding name 
Worksheets("SheetA").Range(Name & lastrow).Copy 
Worksheets("summary").Range("a65536").End(xlUP).Offset(2,1) 
'Now copy Periods and prices 
Worksheets("SheetA").Range(Name & lastrow).Copy 
Worksheets("summary").Range("a65536").End(xlUP).Offset(2,2) 
'Now copy weights 
Worksheets("SheetB").Range(Name & lastrow).Copy 
Worksheets("summary").Range("a65536").End(xlUP).Offset(2,3) 
Next 

可惜我沒能得到這個工作。我猜想有一些偏移問題。

+0

偏移量是在一系列的方法,你想@chrisneilsen我編輯的代碼,並嘗試過,但它仍然無法正常工作,使用它在工作表 – 2015-03-30 23:31:03

+0

。感謝您指出編輯。 – Jain 2015-03-30 23:53:06

回答

1

首先讓我們看看您現有的代碼。


For Each Name In Range("B1:D1")

這假定3種果樹。當你添加第四個時,你將不得不更新這個代碼,並且當你添加第五個時再次更新這個代碼。決定哪些水果感興趣,維持宏觀的人是否?如果沒有,每次添加水果時,他們都必須要求更新宏。

決定什麼樣的未來可能發生的變化,允許一個平衡:

  • 這幾乎是沒有力氣允許額外的水果或額外的時間,並且在大多數情況下,這是一個非常可能的變化,所以我通常允許它。
  • 目前你有價格和重量作爲有趣的屬性。允許新房產可能會非常棘手;我通常不會打擾。
  • 水果是否在同一個序列?這些時期是否以相同的順序?考慮到這些變化比允許額外的水果或時期更麻煩,所以我應該允許這些變化嗎?在以前的生活中,我負責許多類似的任務。工作表格的格式經常被我無法理解的原因所改變。如果我簡單地認爲工作表是我期望的格式,我可以創建現實但錯誤的摘要,並且錯誤可能在一段時間內不會被識別。至少,我總是按照我預期的格式對工作表進行檢查。

我不是要你同意我對準備什麼變化的評估,因爲我對你的申請一無所知。我要求你考慮這個問題。您未檢查的更改可能會導致損壞的摘要或崩潰的宏。這有多重要?你已經檢查過但沒有處理的更改意味着只有更新它才能運行宏。這有多重要?


Worksheets("summary").Range("a65536").End(xlUP).Offset(2,1)

到Excel 2007年之前,工作表有65536行,以便細胞A65536是自2007年以來已誰編碼列A.任何的底部會建議Cells(Rows.Count, 1),而不是Range("a65536")因爲它指定底部列的A爲當前版本的Excel,無論它是什麼。

我不喜歡Offset,因爲您必須執行心算以確定哪個單元格正在尋址。如果週期數不總是正好三個,則必須在偏移行上執行算術運算。那就是:Offset(2, 1)將不得不被Offset(2+Period-1, 1)之類的東西取代。另外,您已經開始在列A的底部,在執行偏移量之前將其移動到列中的第一個單元格。

如果您的代碼每天要執行數百萬次,那麼將運行時間減少一毫秒可能是合適的,但在這裏適合嗎?您需要花多長時間編寫這些代碼(反正無法使用),以及您的代碼的未來維護人員需要多長時間才能瞭解您正在執行的操作?我的建議是使代碼簡單易寫,除非有一些壓倒性的原因使其複雜且難以編寫。

我的代碼包含了一些節省時間的小技巧。這些都很容易實現,可以自動化。如果您需要10秒或20秒才能輸入一條能夠爲用戶節省大量時間的聲明,那麼公司可以在幾個月內獲得投資回報(您的編碼時間爲<用戶的等待時間)。此外,這些技巧中的一些使未來的維護更容易。對於需要在6個月或12個月內更新此宏的人員,請始終讓生活更輕鬆,因爲此人可能是您。


請不要使用「SheetA」或「SheetB」這樣的名稱。 「價格」和「重量」等名稱會立即告訴您工作表的用途。有意義的名字讓事情變得如此簡單。


我認爲這就夠批評了。

仔細研究此代碼。有很多評論解釋我正在嘗試什麼,但很少有評論解釋每個陳述的作用,所以如果你不知道也不能猜測,你將不得不查看那些信息。使用F8逐句通過宏語句。你明白每個陳述的作用,爲什麼我想要這樣做?如有必要,請回答問題,但越多,你可以爲自己制定更快,你會發展自己的技能。

Option Explicit 

' Constants make maintenance so much easier: 
' * You code is full of meaningful names rather than numbers whos purpose 
' must be looked up. 
' * If columns are rearranged or an extra heading line added to one of the 
' worksheets, one change here and the problem is fixed. 
Const ColPWPeriod As Long = 1 
Const ColPWDataFirst As Long = 2 
Const ColSummaryFruit As Long = 1 
Const ColSummaryPeriod As Long = 2 
Const ColSummaryPrice As Long = 3 
Const ColSummaryWeight As Long = 4 
Const ColSummaryLast As Long = 4 
Const RowPWFruit As Long = 1 
Const RowPWDataFirst As Long = 3 
Sub CombineABIntoS() 

    Dim ColPriceLast As Long 
    Dim ColPWCrnt As Long 
    Dim ColWeightLast As Long 
    Dim FruitCrnt As String 
    Dim RowPriceLast As Long 
    Dim RowPWCrnt As Long 
    Dim RowSummaryCrnt As Long 
    Dim RowWeightLast As Long 
    Dim WshtPrice As Worksheet 
    Dim WshtWeight As Worksheet 
    Dim WshtSummary As Worksheet 

    ' Updating the screen for each change can be very time consuming. 
    Application.ScreenUpdating = False 

    ' * It takes the interpreter a noticable fraction of a second to process 
    ' Worksheets("Xxxxx") because it has to look "Xxxxx" up in its collection 
    ' of worksheet names. These cause these look ups to be performed once and 
    ' the result stored. With all the switching between worksheets this can 
    ' reduce duration noticably. 
    ' * If the names of the worksheets change, only these statements will need 
    ' amendment to fully update the macro. 
    ' * These are not your names. If you do not accept my advice, change to 
    ' your worksheet names 
    Set WshtPrice = Worksheets("Price") 
    Set WshtWeight = Worksheets("Weight") 
    Set WshtSummary = Worksheets("Summary") 

    ' For price worksheet, find last row with a period and last column with a fruit 
    With WshtPrice 
    ColPriceLast = .Cells(1, Columns.Count).End(xlToLeft).Column 
    RowPriceLast = .Cells(Rows.Count, ColPWPeriod).End(xlUp).Row 
    End With 

    ' For weight worksheet, find last row with a period and last column with a fruit 
    With WshtWeight 
    ColWeightLast = .Cells(1, Columns.Count).End(xlToLeft).Column 
    RowWeightLast = .Cells(Rows.Count, ColPWPeriod).End(xlUp).Row 
    End With 

    ' Check worksheets match. 
    ' Check same number of fruits 
    If ColPriceLast <> ColWeightLast Then 
    Call MsgBox("Worksheet " & WshtPrice.Name & " has " & _ 
       ColPriceLast - ColPWDataFirst + 1 & _ 
       " fruit while worksheet " & WshtWeight.Name & " has " & _ 
       ColWeightLast - ColPWDataFirst + 1 & _ 
       ". Sorry I cannot handle this situation", _ 
       vbOKOnly, "Combine Price and Weight worksheets") 
    Exit Sub 
    End If 
    ' Check same number of periods 
    If RowPriceLast <> RowWeightLast Then 
    Call MsgBox("Worksheet " & WshtPrice.Name & " has " & _ 
       RowPriceLast - RowPWDataFirst + 1 & _ 
       " periods while worksheet " & WshtWeight.Name & " has " & _ 
       RowWeightLast - RowPWDataFirst + 1 & _ 
       ". Sorry I cannot handle this situation", vbOKOnly, _ 
       "Combine Price and Weight worksheets") 
    Exit Sub 
    End If 
    ' Check same fruits in same sequence. 
    ' Note: have already checked ColPriceLast = ColWeightLast 
    For ColPWCrnt = ColPWDataFirst To ColPriceLast 
    If WshtPrice.Cells(RowPWFruit, ColPWCrnt).Value <> _ 
     WshtWeight.Cells(RowPWFruit, ColPWCrnt).Value Then 
     Call MsgBox("Cell " & ColNumToCode(ColPWCrnt) & RowPWFruit & _ 
        " of worksheet " & WshtPrice.Name & " = """ & _ 
        WshtPrice.Cells(RowPWFruit, ColPWCrnt).Value & _ 
        """ while the same cell in worksheet " & _ 
        WshtWeight.Name & " = """ & _ 
        WshtWeight.Cells(RowPWFruit, ColPWCrnt).Value & _ 
        """. Sorry I cannot handle this situation", vbOKOnly, _ 
        "Combine Price and Weight worksheets") 
     Exit Sub 
    End If 
    Next 
    ' Check same periods in same sequence. 
    ' Note: have already checked RowPriceLast = RowWeightLast 
    For RowPWCrnt = RowPWDataFirst To RowPriceLast 
    If WshtPrice.Cells(RowPWCrnt, ColPWPeriod).Value <> _ 
     WshtWeight.Cells(RowPWCrnt, ColPWPeriod).Value Then 
     Call MsgBox("Cell " & ColNumToCode(ColPWPeriod) & RowPWCrnt & _ 
        " of worksheet " & WshtPrice.Name & " = """ & _ 
        WshtPrice.Cells(RowPWCrnt, ColPWPeriod).Value & _ 
        """ while the same cell in worksheet " & _ 
        WshtWeight.Name & " = """ & _ 
        WshtWeight.Cells(RowPWCrnt, ColPWPeriod).Value & _ 
        """. Sorry I cannot handle this situation", vbOKOnly, _ 
        "Combine Price and Weight worksheets") 
     Exit Sub 
    End If 
    Next 

    ' Formats of two worksheets match 

    ' For summary worksheet, clear existing contents, create header row 
    ' and initialise row counter 
    With WshtSummary 
    .Cells.EntireRow.Delete ' Clear any existing contents 
    .Cells(1, ColSummaryFruit).Value = "Fruit" 
    .Cells(1, ColSummaryPeriod).Value = "Period" 
    .Cells(1, ColSummaryPrice).Value = "Price" 
    .Cells(1, ColSummaryWeight).Value = "Weight" 
    .Range(.Cells(1, 1), .Cells(1, ColSummaryLast)).Font.Bold = True 
    RowSummaryCrnt = 2 
    End With 

    For ColPWCrnt = ColPWDataFirst To ColPriceLast 
    ' Can copy across fruit from either worksheet since checked to match 
    WshtSummary.Cells(RowSummaryCrnt, ColSummaryFruit).Value = _ 
            WshtPrice.Cells(RowPWFruit, ColPWCrnt).Value 
    For RowPWCrnt = RowPWDataFirst To RowPriceLast 
     If WshtPrice.Cells(RowPWCrnt, ColPWCrnt).Value <> "" Or _ 
     WshtWeight.Cells(RowPWCrnt, ColPWCrnt).Value <> "" Then 
     ' There is either a price or a weight or both for this period and fruit 
     ' Can copy across period from either worksheet since checked to match 
     WshtSummary.Cells(RowSummaryCrnt, ColSummaryPeriod).Value = _ 
            WshtPrice.Cells(RowPWCrnt, ColPWPeriod).Value 
     ' Copy across price and weight 
     WshtSummary.Cells(RowSummaryCrnt, ColSummaryPrice).Value = _ 
            WshtPrice.Cells(RowPWCrnt, ColPWCrnt).Value 
     WshtSummary.Cells(RowSummaryCrnt, ColSummaryWeight).Value = _ 
            WshtWeight.Cells(RowPWCrnt, ColPWCrnt).Value 
     ' Step summart row ready fro next period or fruit 
     RowSummaryCrnt = RowSummaryCrnt + 1 
     End If 
    Next RowPWCrnt 
    Next ColPWCrnt 

End Sub 
Function ColNumToCode(ByVal ColNum As Long) As String 

    Dim Code As String 
    Dim PartNum As Long 

    ' Last updated 3 Feb 12. Adapted to handle three character codes. 
    If ColNum = 0 Then 
    ColNumToCode = "0" 
    Else 
    Code = "" 
    Do While ColNum > 0 
     PartNum = (ColNum - 1) Mod 26 
     Code = Chr(65 + PartNum) & Code 
     ColNum = (ColNum - PartNum - 1) \ 26 
    Loop 
    End If 

    ColNumToCode = Code 

End Function 
+0

謝謝先生。我仍然適合我的數據,一定會問任何問題。 – Jain 2015-03-31 21:03:47

相關問題