Excel VBA Copy specific Column from different Worksheets - vba

I'm currently developing a monitoring Tool in Excel using VBA and encountered some difficulties when copying data.
Current Code:
Sub CopyID()
'Copies entire Row of IDs from "Sheet 2" to main Sheet "Main Sheet"
Dim lastCell As Long
LastCell = Cells(Rows.Count,'Sheet 2':M).End(xlUp).Row
'Missing here: Copy to Column 1 at Row 3!
Sheets("Sheet 2").Columns(M).Copy Destination:=Sheets("Main Sheet").Columns(1)
End Sub
What it is supposed to do:
Copy the Data of Sheet2_Column M starting at Row 2
to
Main Sheet Colum A sarting at Row 3
Also, I don't know if this is possible yet, use a specific formula for the destination (Formular is: =LEFT(Data,10))
I am glad for any response to this as I'd like to learn how these "Copy Methods" work in detail and am happy for any tipps and tricks regarding these methods.
Edit//
The Copy Part should work like this
Sheet 2 Contains a Colum that has a headercell and X cells with a value that has a similar format.
Example of the Sheet 2 Contents
This is a row in Sheet 2. I only need the first 10 digits of the content of the cells. Is it possible to include that as a formula similar to
=Left(Sheet 2:M2,10)
so it works like this:
"sheet 2" cell content: "1234567891_1_123X" copy to "main sheet" as "1234567891"

Define your source and destination worksheet. And range/column names bust be submitted as strings like "M".
Sub CopyID()
'Copies entire Row of IDs from "Sheet 2" to main Sheet "Main Sheet"
Dim WsSource As Worksheet
Set WsSource = ThisWorkbook.Worksheets("Sheet 2")
Dim WsDestination As Worksheet
Set WsDestination = ThisWorkbook.Worksheets("Main Sheet")
Dim lastRow As Long
lastRow = WsSource.Cells(WsSource.Rows.Count, "M").End(xlUp).Row
'Missing here: Copy to Column 1 at Row 3!
WsSource.Range("M2:M" & lastRow).Copy Destination:=WsDestination.Range("A3")
End Sub
Edit:
To copy only the first 10 characters of each cell would need a process for each value:
Option Explicit
Public Sub CopyID()
'Copies entire Row of IDs from "Sheet 2" to main Sheet "Main Sheet"
Dim WsSource As Worksheet
Set WsSource = ThisWorkbook.Worksheets("Sheet 2")
Dim WsDestination As Worksheet
Set WsDestination = ThisWorkbook.Worksheets("Main Sheet")
Dim lastRow As Long
lastRow = WsSource.Cells(WsSource.Rows.Count, "M").End(xlUp).Row 'Find last row in column M
Dim ArrSource As Variant
ArrSource = WsSource.Range("M2:M" & lastRow).Value 'read column m values into array
Dim i As Long
For i = 1 To UBound(ArrSource) 'process each value in the array
ArrSource(i, 1) = Left$(ArrSource(i, 1), 10) 'keep only left 10 characters
Next i
WsDestination.Range("A3").Resize(UBound(ArrSource), 1).Value = ArrSource 'write array into destination
End Sub
Note .Resize(UBound(ArrSource), 1) defines the destination the same size as the array is that we want to insert.

Related

Copying cell value(s) based on values in adjecent cell

I've got a beautiful Excel file which automatically imports values from CSV files into my worksheet, the data is pasted in the first empty row of my sheet.
The thing is that data can come from 3 different sources, say the column G is filled with either a 1, a 2 or a 3.
Based on the value in said column i'd like to paste the other values of that row to the first empty cell in a specific range in a different sheet. The sheet name is dependent on the Value in Column C, for which I created the following code:
Sub Lastcell()
Dim LR As String
Dim SheetName As String
LR = Cells(Rows.Count, "B").End(xlUp).Row
SheetName = Range("C" & LR).Value
If SheetExists(SheetName) Then
Else
Sheets.Add(After:=Sheets(Sheets.Count)).name = SheetName
End If
End Sub
Function SheetExists(SheetName As String, Optional Wb As Workbook) As Boolean
If Wb Is Nothing Then Set Wb = ThisWorkbook
On Error Resume Next
SheetExists = (LCase(Wb.Sheets(SheetName).name) = LCase(SheetName))
On Error GoTo 0
End Function
So I know which worksheet I’m copying to, now I want to select which row it goes to.
Say, if the value in the last cell of column G is 1, I want to copy the whole row to the first empty cell in row C, starting from C5.
if the value in the last cell of column G is 2, I want to copy the whole row to the first empty cell in row H, starting from H5.
if the value in the last cell of column G is 3, I want to copy the whole row to the first empty cell in row M, starting from M5.
My question is: How can i select a different paste range based on the value of a cell. Cell value is 1, paste to last empty cell in column A Cell value is 2, Paste to last empty cell in column B Cell value is 3, Paste to last empty cell in column C?
Something like this?
Sub tgr()
Dim wb As Workbook
Dim wsData As Worksheet
Dim wsDest As Worksheet
Dim LR As Long, NR as long
Dim DestCol As String
Set wb = ActiveWorkbook
Set wsData = wb.ActiveSheet
LR = wsData.Cells(wsData.Rows.Count, "G").End(xlUp).Row
On Error Resume Next
Set wsDest = wb.Sheets(wsData.Cells(LR, "C").Value)
On Error GoTo 0
If Not wsDest Is Nothing Then
Select Case wsData.Cells(LR, "G").Value
Case 1: DestCol = "C"
Case 2: DestCol = "H"
Case 3: DestCol = "M"
End Select
'Destination sheet and columns are now defined
'Copy over what you want to the destination
NR = wsDest.Cells(wsDest.Rows.Count, DestCol).End(xlUp).Row
If NR < 5 Then NR = 5
wsDest.Cells(NR, DestCol).Resize(, 6).Value = wsData.Cells(LR, "A").Resize(, 6).Value
End If
End Sub

How to do a partial look up in excel and get the data in next column till four rows in VBA

I have sheet 1 with Column name: Main task
MainTask
And, I have Sheet 2 where the Sub-tasks are given based on the characters between 1st and 2nd hyphen(-) of the Data in Main Task for eg: Under the main task column there is "Pyramid - IoT Forecast - Latin America - Argentina - 2017". So, based on the string " IoT Forecast" the sub tasks are given as in the below image.
Out Put:
Now In sheet 3 I need every title from the main task should be copied and pasted from the Sheet 1 and look for relevant sub tasks and pasted in the next column like the below image.
I have used, Wild cards, partial V-look up with Mid Function but only single sub task is populating. Please help me provide code in VBA.
Your Sheet 3 is identical to Sheet 2 but with the full main task in it instead of just the extract. I suggest the following method.
Create a column in Sheet 1 in which you write only the extract. This column would be identical in contents to column A of sheet 2. Use this formula to populate that column (where A2 contains the full main task).
=TRIM(LEFT(MID($A2,FIND("-",$A2)+1,100),FIND("-",MID($A2,FIND("-",$A2)+1,100))-1))
Make a copy of Sheet 2 as Sheet 3 and add a blank column B in it. Populate this column with this formula (where A:A is the column containing the full task, and C:C the column you added in step 1.
=INDEX('Sheet 1'!A:A,MATCH(A2,'Sheet 1'!C:C,0))
Replace the formulas in Sheet 3 with values (Copy / Paste values) and Remove column A from that sheet. Sort this sheet on what is now column A.
Remove the column you added in Sheet 1 to restore Sheet 1 to its original state.
You will need to do an array formula, something similar to the below where the sub category is in C1
=INDEX($A$2:$A$6,SMALL(IF(NOT(ISERROR(SEARCH("-" & $C$1 & "-",$A$2:$A$6))),ROW($A$2:$A$6)-1),ROWS($D$1:D1)))
If you are open to a VBA solution, you may try something like this.
The following code assumes that there are three sheets in the workbook named as "Sheet1", "Sheet2" and "Sheet3".
If the sheet names are different in your original workbook, please change them in the code in following lines before testing the code.
Set ws1 = Sheets("Sheet1")
Set ws2 = Sheets("Sheet2")
Set ws3 = Sheets("Sheet3")
Place the following code on a Standard Module and run the code to get the desired output on Sheet3.
Sub LookupData()
Dim ws1 As Worksheet, ws2 As Worksheet, ws3 As Worksheet
Dim rng As Range, cell As Range, MainTask As Range
Dim lr2 As Long, lr3 As Long
Dim MainTaskStr As String, wht As String
Application.ScreenUpdating = False
Set ws1 = Sheets("Sheet1")
Set ws2 = Sheets("Sheet2")
Set ws3 = Sheets("Sheet3")
lr2 = ws2.Cells(Rows.Count, 1).End(xlUp).Row
Set rng = ws2.Range("A2:A" & lr2)
ws3.Cells.Clear
ws3.Range("A1:B1").Value = Array("Main Task", "Sub-Task")
If ws2.FilterMode Then ws2.ShowAllData
For Each cell In rng
If cell.Value <> MainTaskStr Then
MainTaskStr = cell.Value
lr3 = ws3.Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row + 1
wht = "- " & cell.Value & " -"
Set MainTask = ws1.Range("A:A").Find(what:=wht, LookIn:=xlValues, lookat:=xlPart, MatchCase:=False)
If Not MainTask Is Nothing Then
With ws2.Rows(1)
.AutoFilter field:=1, Criteria1:=MainTaskStr
ws3.Range("A" & lr3) = MainTask.Value
ws2.Range("B2:B" & lr2).SpecialCells(xlCellTypeVisible).Copy ws3.Range("B" & lr3)
End With
End If
End If
Next cell
If ws2.FilterMode Then ws2.AutoFilterMode = False
ws3.UsedRange.Columns.AutoFit
Application.ScreenUpdating = True
End Sub

VBA, Sorting data in worksheets by unqiue strings

My current macro takes my data row by row from workbook A or worksheet A and splits it into different sheets based on matching headers. I am having trouble taking it a step further and splitting the string fields among these sheets.
For example, my data in workbook A, column B, contains 10 unique strings, how can I sort string x to one sheet only, and strings the rest of them to other sheets. So the row that contains sheet x will go to a certain sheet and strings abc will act as normal.
Here is my code so far, specifically call out the workbook and sheet names so it is not dynamic:
Option Explicit
Sub main()
Dim dsRng As Range
Dim sht As Worksheet
Dim AShtColsList As String, BShtColsList As String
Set dsRng = Workbooks("Workbook A").Worksheets("Sample Extract").Range("A1").CurrentRegion '<--| set your entire data set range in workbook "A" worksheet "ShtA" (change "A" and "ShtA" to your actual names)
dsRng.Sort key1:=dsRng.Range("A1"), order1:=xlAscending, Header:=xlYes '<--| sort data set range on its 1st column (which is "A", beginning it from column "A")
With Workbooks("Workbook B") '<--| refer "B" workbook
For Each sht In .Worksheets(Array("Stack", "Documentation", "Users")) '<--| loop through its worksheets
GetCorrespondingColumns dsRng, sht, AShtColsList, BShtColsList '<--| build lists of corresponding columns indexes in both workbooks
CopyColumns dsRng, sht, AShtColsList, BShtColsList '<--| copy listed columns between workbooks
Next sht
End With
End Sub
Sub GetCorrespondingColumns(dsRng As Range, sht As Worksheet, AShtColsList As String, BShtColsList As String)
Dim f As Range, c As Range
Dim iElem As Long
AShtColsList = "" '<--| initialize workbook "A" columns indexes list
BShtColsList = "" '<--| initialize workbook "B" current sheet columns indexes list
For Each c In sht.Rows(2).SpecialCells(xlCellTypeConstants, xlTextValues) '<--| loop through workbook "B" current sheet headers in row 2 *******
Set f = dsRng.Rows(1).Find(what:=c.Value, lookat:=xlWhole, LookIn:=xlValues) '<--| look up data set headers row for workbook "B" current sheet current column header
If Not f Is Nothing Then '<--| if it's been found ...
BShtColsList = BShtColsList & c.Column & "," '<--| ...update workbook "B" current sheet columns list with current header column index
AShtColsList = AShtColsList & f.Column & "," '<--| ...update workbook "A" columns list with corresponding found header column index
End If
Next c
End Sub
Sub CopyColumns(dsRng As Range, sht As Worksheet, AShtColsList As String, BShtColsList As String)
Dim iElem As Long
Dim AShtColsArr As Variant, BShtColsArr As Variant
If AShtColsList <> "" Then '<--| if any workbook "B" current sheet header has been found in workbook "A" data set headers
BShtColsArr = Split(Left(BShtColsList, Len(BShtColsList) - 1), ",") '<--| build an array out of workbook "B" current sheet columns indexes list
AShtColsArr = Split(Left(AShtColsList, Len(AShtColsList) - 1), ",") '<--| build an array out of workbook "A" corresponding columns indexes list
For iElem = 0 To UBound(AShtColsArr) '<--| loop through workbook "A" columns indexes array (you could have used workbook "A" corresponding columns indexes list as well)
Intersect(dsRng, dsRng.Columns(CLng(AShtColsArr(iElem)))).Copy sht.Cells(2, CLng(BShtColsArr(iElem))) '<--| copy data set current column into workbook "B" current sheet corresponding column starting from row 2 *******
Next iElem
End If
End Sub
Thanks.
EDIT
Complete extract. Call this Sample extract in workbook B.
'Users' Sheet. My Macro already does this.
'Documentation' Sheet, my macro already does this too
'Stack' Sheet. my macro does not do this. It filtered the record stackoverflow and its pertaining columns.
Hopefully this helps.
get your data saved in sheet named "data". and below code will generate separate sheets for every unique value in column B with data of corresponding value.
Dim data, sht As Worksheet
Dim rng As Range
Dim counter As Long
Set data = ThisWorkbook.Sheets("data")
data.Activate
Range("B:B").Copy
Range("H:H").PasteSpecial xlPasteValues
Range("H:H").RemoveDuplicates Columns:=1, Header:=xlYes
Set rng = data.Range("H2")
Do While rng.Value <> ""
Set sht = ThisWorkbook.Worksheets.Add
sht.Name = rng.Value
data.Activate
ActiveSheet.AutoFilterMode = False
Range("A1").AutoFilter field:=2, Criteria1:=rng.Value
Range("A1:C1").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.SpecialCells(xlVisible).Copy
sht.Activate
Range("A1").PasteSpecial xlPasteValues
Range("A1").Activate
Set rng = rng.Offset(1, 0)
Loop
It will create sheets in same workbook.

How to copy a range of cells and paste values to two different worksheets?

I have a range of data on Sheet2 that links it to Sheet1 (Sheet1 is formatted and linked by Sheet2 using =if(Sheet2$x$x="","",Sheet2$x$x); this way any data put into the range C13:G62 of Sheet2 shows up in Sheet1 range C13:G62. The beginning portion on the code works to move JUST the data in the specified range to the BATCH file Sheet3 and finds the last row pasting the values from Sheet1 without copying the formulas. It was made this way so I can delete data on Sheet2 to wipe Sheet1 clean but still have all the backup data on one Sheet3.
Anyway, the problem lies when I tried to manipulate the code to copy all contents on Sheet1 (to DUPLICATE SHEET1) to another sheet at the end of the workbook:
Sheets(Sheet1).Copy After:=Sheets(Sheets.Count)
ActiveSheet.Name = _
InputBox("Name of the New WorkSheet")
This allowed me to name the sheet which was great. However by creating multiple variations of code it will not move the DATA in the RANGE to the newly created Sheet4 (there is no data). In one iteration of code I was able to get Sheet1 to copy and make Sheet4 at the end of the work book with no data in the range but have the cursor land in cell C13, the starting point for pasting just the values, and when I left click the mouse in that cell to "paste values" it would paste the values that I was trying to paste. However, either way I rearranged the code, the data would always be copied but would never paste to the Sheet4 range.
Here I have posted one variation of the code IN WHICH IT STILL WILL NOT PASTE THE VALUES TO SHEET4 (THE NEWLY CREATED SHEET) but still copies to the BATCH FILE. What am I missing here?
Dim s1Sheet As Worksheet
Dim s2Sheet As Worksheet
Dim source As String
Dim target As String
Dim rngSource As Range
Dim rngTargetStart As Range
source = "Invoice"
target = "TOTAL_INVOICE"
Application.EnableCancelKey = xlDisabled
Set s1Sheet = Sheets(source)
Set s2Sheet = Sheets(target)
Set rngSource = s1Sheet.Range("C13:G62")
Set rngTargetStart = s2Sheet.Range("C" & Rows.Count).End(xlUp).Offset(1)
'Set rngTargetFinish = ws1.Range("C" & Rows.Count).End(xlUp).Offset(1)
rngTargetStart.Resize(rngSource.Rows.Count, rngSource.Columns.Count).Value = rngSource.Value
'rngTargetFinish.Resize(rngSource.Rows.Count, rngSource.Columns.Count).Value = rngSource.Value
'Set target = Sheets("Sheet4").Range("B13:G63")
copy_non_formulas source:=rngSource, target:=rngTargetStart
' copy_non_formulas source:=Range("B13:G63"), target:=Range("B70:G109") Unhighlight
' copy_non_formulas source:=Range("B13:G63"), target:=Range("B13:G63") Unhighlight
'===Copies Sheet to End of WorkBook & Pastes Values======
Sheets(source).Copy After:=Sheets(Sheets.Count)
ActiveSheet.Name = _
InputBox("Name of the New WorkSheet")
Range("C13:G62").ClearContents
Dim rng As Range
Set rng = ActiveSheet.Range("C13:G62")
rng.ClearContents
Dim s3Sheet As Worksheet
Dim rngTargetStart2 As Range
Set s3Sheet = Sheets(Sheets.Count)
Set rngTargetStart2 = s3Sheet.Range("C" & Rows.Count).End(xlUp).Offset(1)
rngTargetStart2.Resize(rngSource.Rows.Count, rngSource.Columns.Count).Value = rngSource.Value
copy_non_formulas2 source:=rngSource, target2:=rngTargetStart2
copy_non_formulas2 source:=Range("C13:G62"), target2:=Range("C13:G62")
This is an Integrated Public Sub
copy_non_formulas(source As Range, target As Range)
Dim i As Long
Dim j As Long
Dim c As Range
For i = 1 To source.Rows.Count
For j = 1 To source.Columns.Count
Set c = source(RowIndex:=i, ColumnIndex:=j)
If Left(c.Formula, 1) <> "=" Then
target(RowIndex:=i, ColumnIndex:=j).Value = c.Value
End If
Next j
Next i
And another Public Sub for the Second Move
copy_non_formulas2(source As Range, target2 As Range)
Dim x As Long
Dim y As Long
Dim d As Range
For x = 1 To source.Rows.Count
For y = 1 To source.Columns.Count
Set d = source(RowIndex:=x, ColumnIndex:=y)
If Left(d.Formula, 1) <> "=" Then
target2(RowIndex:=x, ColumnIndex:=y).Value = d.Value
End If
Next y
Next x

VBA - Copy data across worksheets

I'm looking to copy data across multiple worksheets. The names of the worksheets are in column L, I want to pick up the data from columns N:R, for that particular line, and then copy that into cells D17:D21 in the corresponding sheet.
Any assistance would be great.
Cheers
DRod
Sub Macro2()
Dim wb As Workbook
Dim ws As Worksheet
Dim wsGet As Worksheet
Dim LCell As Range
Dim sDataCol As String
Dim lHeaderRow As Long
sDataCol = "L" 'Change to be the column you want to match sheet names agains
lHeaderRow = 5 'Change to be what your actual header row is
Set wb = ActiveWorkbook
Set ws = wb.Sheets("Sheet1") 'Change this to be your Summary sheet
'Check for values in sDataCol
With ws.Range(sDataCol & lHeaderRow + 1, ws.Cells(ws.Rows.Count, sDataCol).End(xlUp))
If .Row <= lHeaderRow Then Exit Sub 'No data
'Loop through sDataCol values
For Each LCell In .Cells
If LCell.Text <> "" Then
'Check if sheet named that value exists
If Evaluate("ISREF('" & LCell.Text & "'!A1)") Then
'Found a matching sheet, copy data from columns N:R to cells D17:D21 in the corresponding sheet
Set wsGet = wb.Sheets(LCell.Text)
wsGet.Range("N[ ]:R[ ]").Copy
LCell.Activate
Range("D17:D21").PasteSpecial Paste:=xlPasteValues, Transpose:=True
End If
End If
Next LCell
End With
End Sub
there are some mistakes
wsGet.Range("N[ ]:R[ ]") is not a valid syntax.
while wsGet.Range("N:R")is.
still, that way you get the entire columns, and not just the row you need of them.
you could use "Instersect()" method or the "Resize()" method on that range to get the range you need
with wsGet.Range("N[ ]:R[ ]").Copy you're using ".Copy" method on a "wsGet" sheet range.
use it on the same range (corrected as per the preceeding suggestion) of the "ws" sheet instead
with LCell.Activate, you're activating a "cell" instead of a "sheet".
you should use wb.Sheets(LCell.Text).Activate instead
but you don't need any sheet activation since you have already set "wsGet" as the "destination" sheet, so simply use ".PasteSpecial" method on it