i want a macro to consolidate the data form multiple sheets to one sheet.. here i given the example ..
Sheet 1
a1:Name b1:Age
a2:sathish b2:22
a3:sarathi b3:24
.
sheet 2
a1:Age b1:Name c1:Dept
a2:60 b2:saran c2:Comp sce
a3:31 b3:rajan c3:B.com
the result should be like this
consolidate sheet
a1:Name b1:Age c1:Dept
a2:sathish b2:22
a3:sarathi b3:24
a4:saran b4:60 c4:Comp sce
a5:rajan b5:31 c5:B.com
Here is the code which i used for consolidate data-
Sub consolidate()
Dim sh As Worksheet
Dim DestSh As Worksheet
Dim Last As Long
Dim shLast As Long
Dim CopyRng As Range
Dim StartRow As Long
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
Application.DisplayAlerts = False
On Error Resume Next
ActiveWorkbook.Worksheets("RDBMergeSheet").Delete
On Error GoTo 0
Application.DisplayAlerts = True
Set DestSh = ActiveWorkbook.Worksheets.Add
DestSh.Name = "RDBMergeSheet"
StartRow = 1
For Each sh In ActiveWorkbook.Worksheets
If sh.Name <> DestSh.Name Then
Last = LastRow(DestSh)
shLast = LastRow(sh)
If shLast > 0 And shLast >= StartRow Then
Set CopyRng = sh.Range(sh.Rows(StartRow), sh.Rows(shLast))
If Last + CopyRng.Rows.Count > DestSh.Rows.Count Then
MsgBox "There are not enough rows in the " & _
"summary worksheet to place the data."
GoTo ExitTheSub
End If
CopyRng.Copy
With DestSh.Cells(Last + 1, "A")
.PasteSpecial xlPasteValues
.PasteSpecial xlPasteFormats
Application.CutCopyMode = False
End With
End If
End If
Next
ExitTheSub:
Application.Goto DestSh.Cells(1)
DestSh.Columns.AutoFit
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End Sub
Function LastRow(sh As Worksheet)
On Error Resume Next
LastRow = sh.Cells.Find(What:="*", _
After:=sh.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
On Error GoTo 0
End Function
Function LastCol(sh As Worksheet)
On Error Resume Next
LastCol = sh.Cells.Find(What:="*", _
After:=sh.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Column
On Error GoTo 0
End Function
I can able consolidate the data but can’t re-arrange as per the column title..
Please help me in this ..THanks in advance
First I identify some mistakes and bad practices in your code then I consider how to redesign your macro to achieve your objectives.
Issue 1
The primary purpose of
On Erroris to allow you to terminate tidily if an unexpected error occurs. You should not use it to avoid errors you expect and you should not ignore errors.Consider the functions
LastRowandLastCol. In both cases, if the Find fails, you ignore the error and carry on. But that means these functions return an incorrect value, so you get another error in the calling routine. If the Find fails you should investigate not ignore. This is true of any other error.Issue 2
Find returns Nothing if the sheet is empty. You call functions
LastRowandLastColfor worksheet “RDBMergeSheet” when it is empty. The code should be:Here I have set LastRow to 0 if the worksheet is empty. This ceases to be a side effect of an error but a documented feature of the function: “Return value = 0 means the worksheet is empty.” The calling routine must check for this value and skip any empty worksheets. There are other approaches but the key point is: provide code to handle expected or possible errors in a tidy manner. For function LastCol you need
LastCol = Rng.Column.Issue 3
The minimum syntax for a function statement is:
The two function statements should end:
As Long.Issue 4
Consider: “ActiveWorkbook.Worksheets(“RDBMergeSheet”)”
If you are working on multiple workbooks,
ActiveWorkbookis not enough. If you are only working on one workbook,ActiveWorkbookis unnecessary. Please do not work with multiple workbooks until your understanding of Excel VBA is better.Issue 5
You delete worksheet “RDBMergeSheet” and then recreate it which hurts my soul. More importantly, you have lost the column headings. I will discuss this matter further under Redesign.
Replace:
with:
You use
Rows.Count,WithandCellsin your code so I will not explain them..Range(.Cells(RowTop, ColLeft), .Cells(RowBottom, ColRight))is an easy method of specifying a range with the top left and bottom right cells.I have used
.EntireRowso I do not need the column numbers. The following gives the same effect:As far as I know
ClearContents(which some people favour) has the same effect asDelete. It certainly takes the same number of micro-seconds. For the usages above, both remove any values or formatting from the second row to the last row of the worksheet.The above change means that row 1 is unchanged and the column widths are not lost. I do not need AutoFit which you have used.
Issue 6
Please be systematic in the naming of your variables. You use
StartRowas the first row andshLastas the last row of the source worksheet andLastas the last row of the destination worksheet. Will a colleague who takes over maintenance of your macro find this easy to understand? Will you remember it in six months when this macro needs some maintenance?Develop a naming system that works for you. Better still, get together with colleagues and agree a single system so all your employer’s macros look the same. Document this system for the benefit of future staff. I would name these variables: RowNumDestLast, RowNumSrcStart and RowNumSrcLast. That is: <purpose of variable> <worksheet> <purpose within worksheet>. This system works for me but your system could be completely different. The key feature of a good system is that you can look at your code in a year and immediately know what each statement is doing.
Issue 7
You set StartRow to 1 and never change it so if
shLast >= StartRowthenshLast > 0. The following is enough:Issue 8
It is good that you are checking for conditions that will result in fatal errors but is this the most likely error? Even if you are using Excel 2003, you have room for 65,535 people and a heading line. You will break the size limit on a workbook before you exceed the maximum number of rows.
Issue 9
This includes the heading row in the range to be copied. Since I will suggest a totally different method later, I will not suggest a correction.
Issue 10
Why are you pasting the values and formats separately?
Redesign
With the corrections above, the code sort of works. With your source data, it sets the destination sheet to:
This is not what you seek. So the rest of this answer is about design: how do you achieve the appearance you seek? There are many approaches but I offer one and explain why I have picked it without discussing alternatives.
Key issues:
I have decided to use the existing column names within worksheet “RDBMergeSheet” to determine the sequence. To prepare the macro for a new column name, just add that name to “RDBMergeSheet”. If I discover a column name in a source sheet that is not in “RDBMergeSheet”, I add it on the right. This second decision will highlight the error if a column name is misspelt but will not be a benefit if someone is collecting extra information in a source worksheet.
I do not copy formats to worksheet “RDBMergeSheet” since, if the source worksheets are formatted differently, each part of worksheet “RDBMergeSheet” would be different.
New statements and explanations
A constant means I use the name in the code and can change the value by changing the Const statement.
I assume the first row of every worksheet contains column names and the first data row is 2. I use a constant to make this assumption clear. It would be possible to use this to write code that would handle a different number of heading rows but I have not done so because it would complicate the code for little advantage.
.Cells(1, Columns.Count)identifies the last column of row 1 which I assume is blank..End(xlToLeft)is the VBA equivalent of the keyboard Ctrl+Left. If.Cells(1, Columns.Count)is blank,.Cells(1, Columns.Count).End(xlToLeft)returns the first cell to the left which is not blank..Columngives the column number of that cell. That is, this statement sets ColNumDestStart to the column number of the last cell in row 1 with a value.This copies the values from row 1 to the variant array ColHeadDest. ColHeadDest will be redimensioned by this statement to
(1 to 1, 1 to ColNumDestLast). The first dimension is for the rows, of which there is only one, and the second dimension is for the columns.Replacement consolidate
I hope I have added enought comments for the code to make sense. You still need the corrected
LastRowandLastCol. I could have replacedLastRowandLastColbut I think I have provided enough new code to be getting on with.