How to update existing data from Sheet1 to Sheet2 using Macro? - vba

I just want to ask if someone do have a code for this.
I have a saved data in Sheet2 and I want to update it using the new data from Sheet1. In the below example, the code will search for Family "Oh" in Sheet2 and update its details using the updated information from Sheet1 when I click on the Update button. Here are the screenshots of
Sheet1:
and
Sheet2:
Tried this code but I can't get it to work correctly
Sub FindValues()
Dim lookUpSheet As Worksheet, updateSheet As Worksheet
Dim valueToSearch As String
Dim i As Integer, t As Integer
Set lookUpSheet = Worksheets("sheet1")
Set updateSheet = Worksheets("sheet2")
'get the number of the last row with data in sheet1 and in sheet2
lastRowLookup = lookUpSheet.Cells(Rows.Count, "A").End(xlUp).Row
lastRowUpdate = updateSheet.Cells(Rows.Count, "A").End(xlUp).Row
'for every value in column A of sheet2
For i = 1 To lastRowUpdate
valueToSearch = updateSheet.Cells(i, 1)
'look the value in column A of sheet1
For t = 1 To lastRowLookup
'if found a match, copy column B value to sheet1 and proceed to the next value
If lookUpSheet.Cells(t, 1) = valueToSearch Then
updateSheet.Cells(i, 2) = lookUpSheet.Cells(t, 2)
Exit For
End If
Next t
Next i
End Sub
Thank you in advance for your help

The following should do what you expect, I've commented the code so you may understand what it is doing:
Sub FindValues()
Dim lookUpSheet As Worksheet, updateSheet As Worksheet
Dim valueToSearch As String
Dim i As Long, t As Long
Set lookUpSheet = Worksheets("Sheet1")
Set updateSheet = Worksheets("Sheet2")
lastRowLookup = lookUpSheet.Cells(Rows.Count, "A").End(xlUp).Row
lastRowUpdate = updateSheet.Cells(Rows.Count, "A").End(xlUp).Row
'get the number of the last row with data in sheet1 and in sheet2
For i = 2 To lastRowLookup 'i = 2 to last to omit the first row as that row is for headers
valueFamily = lookUpSheet.Cells(i, 1) 'Family, 1 = Column A
valueDOB = lookUpSheet.Cells(i, 2) 'DOB, 2 = Column B
valueName = lookUpSheet.Cells(i, 3) 'Name, 3 = Column C
valueAge = lookUpSheet.Cells(i, 4) 'Age, 4 = Column D
'above get the values from the four column into variables
For t = 2 To lastRowUpdate 't = 2 to last to omit the first row as that row is for headers
If updateSheet.Cells(t, 1) = valueFamily And updateSheet.Cells(t, 2) = valueDOB And updateSheet.Cells(t, 3) = valueName Then
'if family, dob and name match, then
updateSheet.Cells(t, 4) = valueAge
'update age value
Exit For
End If
Next t
Next i
End Sub
This could be shortened without using the variables and comparing cells instead like below:
Sub FindValues()
Dim lookUpSheet As Worksheet, updateSheet As Worksheet
Dim i As Long, t As Long
Set lookUpSheet = Worksheets("Sheet1")
Set updateSheet = Worksheets("Sheet2")
lastRowLookup = lookUpSheet.Cells(Rows.Count, "A").End(xlUp).Row
lastRowUpdate = updateSheet.Cells(Rows.Count, "A").End(xlUp).Row
'get the number of the last row with data in sheet1 and in sheet2
For i = 2 To lastRowLookup 'i = 2 to last to omit the first row as that row is for headers
For t = 2 To lastRowUpdate 't = 2 to last to omit the first row as that row is for headers
If updateSheet.Cells(t, 1) = lookUpSheet.Cells(i, 1) And updateSheet.Cells(t, 2) = lookUpSheet.Cells(i, 2) And updateSheet.Cells(t, 3) = lookUpSheet.Cells(i, 3) Then
'if family, dob and name match, then
updateSheet.Cells(t, 4) = lookUpSheet.Cells(i, 4)
'update age value
Exit For
End If
Next t
Next i
End Sub
The issue you were having is from the fact that you needed to have the IF Statement look at the first 3 cells instead of a single value, so with the AND between conditions you compare all three.

This is how to update to sql using adodb.
Sub UpdateSQL()
Dim Cn As Object
Dim strConn As String, Name As String
Dim Ws As Worksheet
Dim strSQL As String
Dim i As Integer
Dim vDB
strConn = "Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=" & ThisWorkbook.FullName & ";" & _
"Extended Properties=Excel 12.0;"
Set Ws = Sheets(1)
Name = Sheets(2).Name
With Ws
vDB = .Range("a2", .Range("d" & Rows.Count).End(xlUp))
End With
Set Cn = CreateObject("ADODB.Connection")
Cn.Open strConn
For i = 1 To UBound(vDB, 1)
strSQL = "UPDATE [" & Name & "$] set Age=" & vDB(i, 4) & " where Family = '" & vDB(i, 1) & "' AND DOB =#" & vDB(i, 2) & "# AND Name='" & vDB(i, 3) & "' "
Cn.Execute strSQL
Next i
Cn.Close
Set Cn = Nothing
End Sub

Related

SQL Query with n number of WHERE-arguments in VBA

I’m using ADO to run SQL query in VBA. I’ve done this quite a lot, and everything works properly.
However, I’m advancing to a more sophisticated query, where I need to input an unknown number of conditional strings. In short:
SELECT * FROM database.dbo.table
WHERE Col1 IN (‘val1’, ‘val2’, ..., ‘valn’)
I have a set of data on my worksheet, which changes every time. The data are of the same string format each time, but number of cells with values varies. I want to execute above query, using my n number of variables in the WHERE-statement.
Example of query with 5 variables from worksheet:
SELECT * FROM database.dbo.table
WHERE Col1 IN (‘000165234’, ‘000165238’, ‘000165231’, ‘000165232’, ‘000165239’)
Any pointers to the right direction are greatly appreciated.
My biggest issue is how to handle the unknown number of variables.
Constraints: will always be at least 1 cell with value, and never more than 60.
Notes: Data is also stored in an array, and does not necessarily needs to be printed on the worksheet.
Updated code
Sub TEST()
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Set ws1 = ThisWorkbook.Worksheets("Sheet1")
Set ws2 = ThisWorkbook.Worksheets("Sheet2")
Dim fRow As Long
Dim sRow As Integer
Dim col As Integer
Dim arr() As Variant
Dim coll As New Collection
col = 3
sRow = 6
With ws1
fRow = .Cells(.Rows.Count, col).End(xlUp).Row
End With
With ws2
fRow2 = .Cells(.Rows.Count, 12).End(xlUp).Row
End With
For i = sRow To fRow
With ws1
ele1= .Cells(i, 2).Value
ele2= "000" & .Cells(i, 4).Value
If ele1<> "" Then
coll.Add Array(ele2)
End If
End With
Next
On Error GoTo gotcha
ReDim arr(1 To coll.Count, 1 To 2)
For i = 1 To coll.Count
arr(i, 1) = coll(i)(0)
Next
gotcha:
Debug.Print Err.number
If Err.number = 9 Then
MsgBox "Error"
Exit Sub
End If
ws2.Range("L29:M" & fRow2).ClearContents
ws2.Range("L29").Resize(UBound(arr, 1), UBound(arr, 2)).Value = arr
Set conn = CreateObject("ADODB.Connection")
Dim fRow3 As Long
With ws2
fRow3 = .Cells(.Rows.Count, 13).End(xlUp).Row
End With
Dim CONNECTION As String
Dim QUERY As String
Dim WHERE As String
'Set connection and SELECT query
CONNECTION = "Provider=*.1;Persist Security Info=True;User ID=*; Password=*; Data Source=*;Initial Catalog=*"
selectpart = "SELECT *FROM database.dbo.table "
'### The error occurs here ###
conditionpart = "WHERE [COL1] IN ('" & Join(arr, "','") & "')"
GetBreakerQuantitiesQuery = selectpart & vbNewLine & conditionpart
QUERY = GetBreakerQuantitiesQuery
conn.Open CONNECTION
Set rs = CreateObject("ADODB.Recordset")
rs.ActiveConnection = conn
rs.Open QUERY
ws.Range("T6").CopyFromRecordset rs
ws.Range("T6:AL6").Copy
ws.Range("N7").PasteSpecial xlPasteValues, xlPasteSpecialOperationNone, True, True
ws.Range("T6:AL6").ClearContents
ws.Range("L6").Select
rs.Close
conn.Close
Set conn = Nothing
Set rs = Nothing
End Sub
Dim sql as string, arr
arr = Array("000165231", "000165232", "000165239")
sql = "SELECT * FROM database.dbo.table WHERE Col1 IN ('" & Join(arr, "','") & "')"
'use sql variable for your query
Use a 1-d array:
For i = sRow To fRow
With ws1
If Len(.Cells(i, 2).Value) > 0 Then
coll.Add "000" & .Cells(i, 4).Value
End If
End With
Next
On Error GoTo gotcha '??
ReDim arr(0 To coll.Count-1)
For i = 1 To coll.Count
arr(i - 1) = coll(i)
Next
'....
ws2.Range("L29").Resize(UBound(arr) + 1, 1).Value = Application.Transpose(arr)

Find the cell adresses for each cell that starts with a specific number

I am looking for a code, that can find each cell that starts with the number "2347" in column L. I want to get the cell adresses for these cells and display it in a MessageBox for example "Msgbox: Cells L3500:L3722 has a value starts starts with "2347" "
Sub Findrow()
Dim MyVal As Integer
Dim LastRow As Long
MyVal = LEFT(c.Value,4) = "2347" _
LastRow = Cells(Rows.Count, "L").End(xlUp).Row
For Each c In Range("L2:L" & LastRow)
If c.Value = Myval Then
This is my code so far. Hope someone can help me!
Using arrays is quite fast
Option Explicit
Public Sub FindIDInColL()
Const VID = "2347" 'Value to find
Dim ws As Worksheet, arrCol As Variant, found As Variant
Set ws = ActiveSheet 'Or Set ws = ThisWorkbook.Worksheets("Sheet3")
arrCol = ws.Range(ws.Cells(2, "L"), ws.Cells(ws.Rows.Count, "L").End(xlUp))
ReDim found(1 To UBound(arrCol))
Dim r As Long, f As Long, msg As String
f = 1
For r = 1 To UBound(arrCol) 'Iterate vals in col L, excluding header row
If Not IsError(arrCol(r, 1)) Then 'Ignore errors
If Len(arrCol(r, 1)) > 3 Then 'Check only strings longer than 3 letters
If Left$(arrCol(r, 1), 4) = VID Then 'Check first 4 letters
found(f) = r + 1 'Capture rows containing value (header offset)
f = f + 1
End If
End If
End If
Next
If f > 1 Then 'If any cells found
ReDim Preserve found(1 To f - 1) 'Drop unused array items
msg = "Cells in col L starting with """ & VID & """" & vbNewLine & vbNewLine
MsgBox msg & " - L" & Join(found, ", L"), , "Total Found: " & f - 1
Else
MsgBox "No cells starting with """ & VID & """ found in col L", , "No matches"
End If
End Sub
Even faster when using the string versions of these functions
Left$() Mid$() Right$() Chr$() ChrW$() UCase$() LCase$()
LTrim$() RTrim$() Trim$() Space$() String$() Format$()
Hex$() Oct$() Str$() Error$
They are more efficient (if Null is not a concern), as pointed out by QHarr
You may try this:
Option Explicit
Sub Findrow()
Dim MyVal As String ' "2347" is a String
Dim LastRow As Long
Dim c As Range, myCells As Range
MyVal = "2347"
LastRow = cells(Rows.Count, "L").End(xlUp).row
Set myCells = Range("M2") 'initialize cells with a dummy cell certainly out of relevant one
For Each c In Range("L2:L" & LastRow)
If Left(c.Value2, 4) = MyVal Then Set myCells = Union(myCells, c) ' if current cell matches criteria then add it to cells
Next
If myCells.Count > 1 Then MsgBox "Cells " & Intersect(myCells, Range("L:L")).Address(False, False) & " have values starting with ‘2347’" ' if there are other cells than the dummy one then get rid of this latter and show their addresses
End Sub

Matching Multiple Criteria and Returning Multiple Values

I have two spreadsheets (wb and wbtemp); both have a column for location and a column for feature type. In VBA, I want to find all of the rows on the second sheet where the two columns are the same as the two columns on a row in the first sheet and get a list or a range made up of the row numbers/indices.
I then want to use this range to pull out values from a different column and find the highest object in it, but I think I will probably be able to do that if I can get this range sorted.
Dim wb As Workbook
Dim ws As Worksheet
Dim Features() As Variant
Dim Activity() As Variant
Dim Benthic As Variant
Dim wbtemp As Workbook
Dim BenSenFeatures() As Variant
Dim BenSenActivity() As Variant
Dim LR As Long
Dim LC As Long
Dim r As Long
Dim c As Long
Dim WhatToFind1 As Variant
Dim WhatToFind2 As Variant
Dim rngFound1 As Range
Dim rngFound2 As Range
Dim rng1 As Variant
Dim rng2 As Variant
Dim rngFound As Range
Dim iLoop As Long
Dim colFound As Range
Set wb = ActiveWorkbook
Set ws = wb.ActiveSheet
Features = ws.Range("B:C").Value
Activity = ws.Rows(1).Value
Benthic = InputBox("Filename goes here...")
Set wbtemp = Workbooks.Open(Benthic, True, True)
With wbtemp
BenSenFeatures = .Sheets(1).Range("A:B").Value
BenSenActivity = .Sheets(1).Rows(1).Value
End With
LR = ws.Range("C" & Rows.Count).End(xlUp).Row
LC = ws.Cells(1, Columns.Count).End(xlToLeft).Column
For r = 3 To LR
If Not IsEmpty(Features(r, 2)) Then
If IsInArray(Features(r, 2), BenSenFeatures, 2) Then
'If WorksheetFunction.Match(Features(r, 2), BenSenFeatures(0, 2), 0) Then <---I tried to use the arrays originally
WhatToFind1 = Features(r, 1)
WhatToFind2 = Features(r, 2)
Set rngFound1 = wbtemp.Sheets(1).Columns(1).Cells(wbtemp.Sheets(1).Columns(1).Cells.Count)
Set rngFound2 = wbtemp.Sheets(1).Columns(2).Cells(wbtemp.Sheets(1).Columns(2).Cells.Count)
For iLoop = 1 To WorksheetFunction.CountIf(wbtemp.Sheets(1).Columns(1), WhatToFind1)
Set rngFound1 = wbtemp.Sheets(1).Columns(1).Cells.Find(WhatToFind1, After:=rngFound1)
rng1(iLoop) = rngFound1.Row
'WorksheetFunction.Index(wbtemp.Sheets(1).Range("A:B").Value,_
WorksheetFunction.Match(WhatToFind1 & WhatToFind2,_
wbtemp.Sheets(1).Columns(1) & wbtemp.Sheets(1).Columns(2),_
0), 1) <---originally tried to use match to search for the multiple criteria but couldn't find a way to create a list of indices
Set rngFound2 = wbtemp.Sheets(1).Columns(2).Cells.Find(WhatToFind2, After:=rngFound2)
rng2(iLoop) = rngFound2.Row
Next iLoop
For Each cell In rng1
If Not Application.CountIf(rng2, cell.Value) = 0 Then
rngFound.Cells(Cells(Rows.Count, 1).End(xlUp) + 1) = cell.Value
End If
Next
I originally tried to use .Match to find the multiple criteria, but I couldn't figure out how to create a range of indices from it. Then I tried using .Find to create two list of indices but I can't figure out how to get that to work. I keep getting
Type Mismatch
errors.
I realise this sounds confusing, so let me know if anything needs clarifying.
Something like this should work for you. I tried to comment the code for clarity.
Sub tgr()
Dim wb As Workbook
Dim ws As Worksheet
Dim rData As Range
Dim wbTemp As Workbook
Dim wsTemp As Worksheet
Dim rTempData As Range
Dim aData() As Variant
Dim aTempData() As Variant
Dim aResults() As Variant
Dim lNumResults As Long
Dim DataIndex As Long, TempIndex As Long, ResultIndex As Long, j As Long
Dim sCritRange1 As String, sCritRange2 As String
Dim sCriteria1 As String, sCriteria2 As String
Set wb = ActiveWorkbook
'Adjust these two as necessary
Set ws = wb.Sheets(1)
Set rData = ws.Range("B3", ws.Cells(ws.Rows.Count, "B").End(xlUp))
'Select wbTemp file
On Error Resume Next
Set wbTemp = Workbooks.Open(Application.GetOpenFilename("Excel Files, *.xls*"))
On Error GoTo 0
If wbTemp Is Nothing Then Exit Sub 'Pressed cancel
'Adjust these two as necessary
Set wsTemp = wbTemp.Sheets(1)
Set rTempData = wsTemp.Range("A1", wsTemp.Cells(wsTemp.Rows.Count, "A").End(xlUp))
sCritRange1 = rTempData.EntireColumn.Address(external:=True)
sCritRange2 = rTempData.Offset(, 1).EntireColumn.Address(external:=True)
sCriteria1 = rData.Address(external:=True)
sCriteria2 = rData.Offset(, 1).Address(external:=True)
lNumResults = Evaluate("SUMPRODUCT(COUNTIFS(" & sCritRange1 & "," & sCriteria1 & "," & sCritRange2 & "," & sCriteria2 & "))")
If lNumResults = 0 Then Exit Sub 'No matches
ReDim aResults(1 To lNumResults, 1 To 3)
aData = rData.Resize(, 2).Value
aTempData = rTempData.Resize(, 2).Value
'Loop through both data ranges
For DataIndex = LBound(aData, 1) To UBound(aData, 1)
For TempIndex = LBound(aTempData, 1) To UBound(aTempData, 1)
'Find where both criteria matches
If aTempData(TempIndex, 1) = aData(DataIndex, 1) And aTempData(TempIndex, 2) = aData(DataIndex, 2) Then
'Match found, add to results and collect the row index
ResultIndex = ResultIndex + 1
aResults(ResultIndex, 1) = aData(DataIndex, 1)
aResults(ResultIndex, 2) = aData(DataIndex, 2)
aResults(ResultIndex, 3) = "Row: " & TempIndex + rTempData.Row - 1 'This is the row index from wsTemp of the found match
End If
Next TempIndex
Next DataIndex
'Row index results gathered
'Do what you want with the results
'In this example it is just providing msgboxes displaying the results
For ResultIndex = LBound(aResults, 1) To UBound(aResults, 1)
MsgBox "Location: " & aResults(ResultIndex, 1) & Chr(10) & _
"Feature: " & aResults(ResultIndex, 2) & Chr(10) & _
"RowIndex: " & aResults(ResultIndex, 3)
Next ResultIndex
'Close wbTemp
wbTemp.Close
End Sub
I made some minor modifications to tigeravatar's answer to get it to work with my data:
Mainly creating a loop which cycled through each row in wb so that the criteria used with CountIfs was a single value and not a range of values.
I swapped the Evaluate("SUMPRODUCT(COUNTIFS(" & sCritRange1 & "," & sCriteria1 & "," & sCritRange2 & "," & sCriteria2 & "))") for Application.WorksheetFunction.CountIfs(Range(sCritRange1), Range(sCriteria1).Value, Range(sCritRange2), Range(sCriteria2).Value)
I would like to thank tigeravatar for their help.
LR = ws.Range("C" & Rows.Count).End(xlUp).Row
LC = ws.Cells(1, Columns.Count).End(xlToLeft).Column
For r = 3 To LR
sCritRange1 = rTempData.EntireColumn.Address(external:=True)
sCritRange2 = rTempData.Offset(, 1).EntireColumn.Address(external:=True)
sCriteria1 = rData(r, 1).Address(external:=True)
sCriteria2 = rData(r, 1).Offset(, 1).Address(external:=True)
lNumResults = Application.WorksheetFunction.CountIfs(Range(sCritRange1), Range(sCriteria1).Value, Range(sCritRange2), Range(sCriteria2).Value)
If lNumResults = 0 Then Exit Sub 'No matches
ReDim aResults(1 To lNumResults, 1 To 3)
aData = rData(r, 1).Resize(, 2).Value
aTempData = rTempData.Resize(, 2).Value
'Loop through both data ranges
For DataIndex = LBound(aData, 1) To UBound(aData, 1)
For TempIndex = LBound(aTempData, 1) To UBound(aTempData, 1)
'Find where both criteria matches
If Not IsEmpty(aTempData(TempIndex, 1)) Then
If aTempData(TempIndex, 1) = aData(DataIndex, 1) And aTempData(TempIndex, 2) = aData(DataIndex, 2) Then
'Match found, add to results and collect the row index
ResultIndex = ResultIndex + 1
aResults(ResultIndex, 1) = aData(DataIndex, 1)
aResults(ResultIndex, 2) = aData(DataIndex, 2)
aResults(ResultIndex, 3) = "Row: " & TempIndex + rTempData.Row - 1 'This is the row index from wsTemp of the found match
End If
End If
Next TempIndex
Next DataIndex
Next r

Convert headers and row level data to column level

I have very little experience working with VBA, so I'm having a hard time looking up what I am trying to do because I am having a hard time putting what I am trying to do into words.
I have been struggling to write a code to do the below task for the past few days.
Basically what I am trying to do is to convert a set of data to different format.
This what my source data looks like.
Data:
and I need it to look like this
FinalLook:
I've a already setup a code which is lengthy and incomplete.
FIRST PART
I started with retrieving a part of a data (AQ:BA) and then convert to the format in sheet2 with the below code.
Sub FirstPart()
Dim lastRow As Long
Dim Laaastrow As Long
Sheets("sheet2").Range("a2:A5000").ClearContents
lastRow = Sheets("Sheet1").Range("c" & Rows.Count).End(xlUp).Row
Sheets("Sheet2").Range("A2:A" & lastRow).Value = Sheets("Sheet1").Range("c5:c" & lastRow).Value
Sheets("Sheet2").Range("b2:l" & lastRow).Value = Sheets("Sheet1").Range("aq5:ba" & lastRow).Value
End Sub
But.. the problem i am facing with this code is that it pulls all the data, i do not want it to pull all the values, but only the ones which is not empty or 0. In other words, if AQ6:BA6 is empty, script should skip this particular row and go the next one.
SECOND PART (converting the sheet2 data to the final format)
Sub NormalizeSheet()
Dim wsSheet2 As Worksheet
Dim wsSheet4 As Worksheet
Dim strKey As String
Dim clnHeader As Collection
Dim lngColumnCounter As Long
Dim lngRowCounterSheet2 As Long
Dim lngRowCounterSheet4 As Long
Dim rngCurrent As Range
Dim varColumn As Variant
Set wsSheet2 = ThisWorkbook.Worksheets("Sheet2")
Set wsSheet4 = ThisWorkbook.Worksheets("Sheet4")
Set clnHeader = New Collection
wsSheet4.Range("c2:c5000").ClearContents
wsSheet4.Range("e2:e5000").ClearContents
wsSheet4.Range("g2:g5000").ClearContents
lngColumnCounter = 2
lngRowCounterSheet2 = 1
Set rngCurrent = wsSheet2.Cells(lngRowCounterSheet2, lngColumnCounter)
Do Until IsEmpty(rngCurrent.Value)
clnHeader.Add rngCurrent.Value, CStr(lngColumnCounter)
lngColumnCounter = lngColumnCounter + 1
Set rngCurrent = wsSheet2.Cells(lngRowCounterSheet2, lngColumnCounter)
Loop
lngRowCounterSheet2 = 2
lngRowCounterSheet4 = 1
lngColumnCounter = 1
Do While Not IsEmpty(wsSheet2.Cells(lngRowCounterSheet2, lngColumnCounter))
Set rngCurrent = wsSheet2.Cells(lngRowCounterSheet2, lngColumnCounter)
strKey = rngCurrent.Value
lngColumnCounter = 2
Do While Not IsEmpty(wsSheet2.Cells(lngRowCounterSheet2, lngColumnCounter))
Set rngCurrent = wsSheet2.Cells(lngRowCounterSheet2, lngColumnCounter)
If rngCurrent.Value = "NULL" Then
Else
wsSheet4.Range("c" & lngRowCounterSheet4).Offset(1, 0).Value = strKey
wsSheet4.Range("e" & lngRowCounterSheet4).Offset(1, 0).Value = clnHeader(CStr(lngColumnCounter))
wsSheet4.Range("g" & lngRowCounterSheet4).Offset(1, 0).Value = rngCurrent.Value
lngRowCounterSheet4 = lngRowCounterSheet4 + 1
End If
lngColumnCounter = lngColumnCounter + 1
Loop
lngRowCounterSheet2 = lngRowCounterSheet2 + 1
lngColumnCounter = 1
Loop
End Sub
I got this code from another thread posted here on stakcoverflow, i modified a bit to get this work.
The problem i am encountering here is that if Sheet2 B2 is empty, the codes doesnt check sheet C2 instead it skips the whole row, which is not right here.
I know this sounds complicated, and this approach of mine may not be even feasible.
Is there ANY OTHER WAY to do this? Is there any other way to get this in a single shot instead of breaking down the data and move each set of columns to sheet2 then to final format?
See how you get on with this. You'll have to adjust range references, and possibly sheet names
Sub x()
Dim r As Long, c As Range
With Sheet1
For r = 5 To .Range("A" & Rows.Count).End(xlUp).Row
For Each c In .Range(.Cells(r, "AQ"), .Cells(r, "BK")).SpecialCells(xlCellTypeConstants)
If c.Value > 0 Then
Sheet2.Range("A" & Rows.Count).End(xlUp)(2).Value = .Range("B1").Value
Sheet2.Range("B" & Rows.Count).End(xlUp)(2).Value = .Cells(r, 1).Value
Sheet2.Range("C" & Rows.Count).End(xlUp)(2).Value = .Cells(r, 2).Value
Sheet2.Range("D" & Rows.Count).End(xlUp)(2).Value = .Cells(3, c.Column).Value
Sheet2.Range("E" & Rows.Count).End(xlUp)(2).Value = .Cells(4, c.Column).Value
Sheet2.Range("F" & Rows.Count).End(xlUp)(2).Value = "(blank)"
Sheet2.Range("G" & Rows.Count).End(xlUp)(2).Value = c.Value
End If
Next c
Next r
End With
Sheet2.Range("A1").Resize(, 7) = Array("TOPHEADER", "HEADER1", "HEADER2", "FROM", "TO", "TYPE", "UNIT")
End Sub

Excel VBA to copy list to new worksheet

I have a list in Excel containing details of people This contains City, Address and name
I need to grab the City column and create a worksheet for each city, then copy the data from sheet1 to that new worksheet.
So if for example I have a city named Dublin, I need the macro to create a new worksheet named dublin, go to the list, grab all the cities named dublin, copy and paste them in the dublin worksheet (as well as the other columns of course)
I am using the macro form this link: http://www.mrexcel.com/forum/excel-questions/727407-visual-basic-applications-split-data-into-multiple-worksheets-based-column.html created by mirabeau.
The code is as follows:
Sub columntosheets()
Const sname As String = "Sheet1" 'change to whatever starting sheet
Const s As String = "A" 'change to whatever criterion column
Dim d As Object, a, cc&
Dim p&, i&, rws&, cls&
Set d = CreateObject("scripting.dictionary")
With Sheets(sname)
rws = .Cells.Find("*", , , , xlByRows, xlPrevious).Row
cls = .Cells.Find("*", , , , xlByColumns, xlPrevious).Column
cc = .Columns(s).Column
End With
For Each sh In Worksheets
d(sh.Name) = 1
Next sh
Application.ScreenUpdating = False
With Sheets.Add(after:=Sheets(sname))
Sheets(sname).Cells(1).Resize(rws, cls).Copy .Cells(1)
.Cells(1).Resize(rws, cls).Sort .Cells(cc), 2, Header:=xlYes
a = .Cells(cc).Resize(rws + 1, 1)
p = 2
For i = 2 To rws + 1
If a(i, 1) <> a(p, 1) Then
If d(a(p, 1)) <> 1 Then
Sheets.Add.Name = a(p, 1)
.Cells(1).Resize(, cls).Copy Cells(1)
.Cells(p, 1).Resize(i - p, cls).Copy Cells(2, 1)
End If
p = i
End If
Next i
Application.DisplayAlerts = False
.Delete
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End With
Sheets(sname).Activate
End Sub
The above is able to create worksheets for each city, but doesn't copy the data into the newly created worksheets. How can this be done? I have very limited knowledge of VBA and am totally lost on this.
Once all the sheets are created, you just need to scour the list in search for cities. For each line, look at the city, and write it in the corresponding sheet. The sheets need to have the same names as the cities for my code to work.
I assume you started in column A, row 1.
dim strCity as string
dim strAdd as string
dim strName as string
for i = 1 to Sheets("[TableSheet]").Cells(Rows.Count, "A").End(xlUp).row
strCity = Sheets("[TableSheet]").range("A" & i)
strAdd = Sheets("[TableSheet]").range("B" & i)
strName = Sheets("[TableSheet]").range("C" & i)
Sheets(strCity).Range("A" & i) = strCity
Sheets(strCity).Range("B" & i) = strAdd
Sheets(strCity).Range("C" & i) = strName
next
[tableSheet] of course is the name of the sheet with your information.If you don't udnerstand and have questions I can gladly answer.
thanks for your swift reply. I used it on a simple list and it worked fine. However, I applied it to a slightly more complex scenario and edited the code as follows:
Dim strDB As String
Dim strName As String
Dim strDate As String
Dim strHour As String
Dim strMin As String
Dim strGR As String
For i = 1 To Sheets("[TableSheet]").Cells(Rows.Count, "B").End(xlUp).Row
strDB = Sheets("[TableSheet]").Range("A" & i)
strName = Sheets("[TableSheet]").Range("B" & i)
strDate = Sheets("[TableSheet]").Range("C" & i)
strHour = Sheets("[TableSheet]").Range("D" & i)
strMin = Sheets("[TableSheet]").Range("E" & i)
strGR = Sheets("[TableSheet]").Range("F" & i)
Sheets(strName).Range("A" & i) = strDB
Sheets(strName).Range("B" & i) = strName
Sheets(strName).Range("C" & i) = strDate
Sheets(strName).Range("D" & i) = strHour
Sheets(strName).Range("E" & i) = strMin
Sheets(strName).Range("F" & i) = strGR
Next
I need to sort by column B. Whenever I run it I keep getting a runtime error '9' Subscript out of range. I know what this means but I can't find where I went wrong in the code.