Create folders using 2 column values from Excel - vba

So I need to make a whole bunch of folders from a spreadsheet.
I have in column A the Surname and in Column B the name of a person, I need to generate folders based on this.
I have found a bit of code that someone else posted, that works, but I need to add a space between the name and surname in the created folder.
The original poster said that they did manage to add a space, but never indicated how.
Sub MakeFoldersForEachRow()
Dim Rng As Range
Dim maxRows, maxCols, r, c As Integer
Dim s As String
Set Rng = Selection
maxRows = Rng.Rows.Count
maxCols = Rng.Columns.Count
For r = 1 To maxRows
s = ""
For c = 1 To maxCols
s = s & Rng(r, c)
Next c
If Len(Dir(ActiveWorkbook.Path & "\" & s, vbDirectory)) = 0 Then
MkDir (ActiveWorkbook.Path & "\" & s)
On Error Resume Next
End If
Next r
End Sub

Please, try the next code:
Sub createFoldNamesFromTwoColumns()
Dim sh As Worksheet, lastR As Long, fldName As String, i As Long
Set sh = ActiveSheet 'use here your necessary sheet
lastR = sh.Range("A" & sh.Rows.count).End(xlUp).row
For i = 1 To lastR
fldName = sh.Range("A" & i) & " " & sh.Range("B" & i)
If Dir(ActiveWorkbook.Path & "\" & fldName, vbDirectory) = "" Then
MkDir ActiveWorkbook.Path & "\" & fldName
End If
Next i
End Sub
Edited:
I could see now your last request, meaning to process the selected columns:
Sub createFoldNamesFromTwoSelectedColumns()
Dim sh As Worksheet, rngSel As Range, C1 As Long, lastR As Long, fldName As String, i As Long
Set sh = ActiveSheet
Set rngSel = Selection
If rngSel.Columns.count <> 2 Then MsgBox "You must select two columns!": Exit Sub
C1 = rngSel.cells(1).Column: Stop
lastR = sh.cells(sh.Rows.count, C1).End(xlUp).row
For i = 1 To lastR
fldName = sh.cells(i, C1) & " " & sh.cells(i, C1 + 1)
If Dir(ActiveWorkbook.Path & "\" & fldName, vbDirectory) = "" Then
MkDir ActiveWorkbook.Path & "\" & fldName
End If
Next i
End Sub

Related

My reconciliation VBA macro takes too long to run when the data is in the thousands

I have a task that requires me to reconcile two sheets of data. I have reformatted them both to have the same format from Column A to M and use the below code to run the reconciliation
It is fine when the data is small but when it gets to thousands of lines, it took 30 min just to run. Is there a way to optimize this code?
The idea is reconcile 2 worksheets then all the matched data go to the 'Matched' worksheet and the unmatched goes to the unmatched worksheet
Dim report_exLR As Long
Dim report_inLR As Long
Dim report_exrng As Range
Dim report_inrng As Range
Set ws_rexternal = ThisWorkbook.Worksheets("Reformat External")
Set ws_rinternal = ThisWorkbook.Worksheets("Reformat Internal")
Set ws_unmatched = ThisWorkbook.Worksheets("Unmatched")
Set ws_matched = ThisWorkbook.Worksheets("Matched")
ex_LR = ws_rexternal.Cells(Rows.Count, 2).End(xlUp).Row
in_LR = ws_rinternal.Cells(Rows.Count, 2).End(xlUp).Row
'concatenate all relevant criteria into one column
For a = 2 To ex_LR
ws_rexternal.Range("T" & a) = ws_rexternal.Range("A" & a) & "," & ws_rexternal.Range("B" & a) & "," & ws_rexternal.Range("C" & a) & "," & ws_rexternal.Range("D" & a) & "," & ws_rexternal.Range("E" & a) & "," & ws_rexternal.Range("F" & a) & "," & ws_rexternal.Range("G" & a) & "," & ws_rexternal.Range("H" & a) & "," & ws_rexternal.Range("I" & a) & "," & ws_rexternal.Range("J" & a) & "," & ws_rexternal.Range("K" & a) & "," & ws_rexternal.Range("L" & a) & "," & ws_rexternal.Range("M" & a)
Next a
For b = 2 To ex_LR
ws_rinternal.Range("T" & b) = ws_rexternal.Range("A" & b) & "," & ws_rexternal.Range("B" & b) & "," & ws_rexternal.Range("C" & b) & "," & ws_rexternal.Range("D" & b) & "," & ws_rexternal.Range("E" & b) & "," & ws_rexternal.Range("F" & b) & "," & ws_rexternal.Range("G" & b) & "," & ws_rexternal.Range("H" & b) & "," & ws_rexternal.Range("I" & b) & "," & ws_rexternal.Range("J" & b) & "," & ws_rexternal.Range("K" & b) & "," & ws_rexternal.Range("L" & b) & "," & ws_rexternal.Range("M" & b)
Next b
'start reconciliation
For a = 2 To ex_LR
For b = 2 To in_LR
If ws_rexternal.Range("T" & a) = ws_rinternal.Range("T" & b) Then
ws_rexternal.Range(Cells(a, 1).Address, Cells(a, 14).Address).Copy Destination:=ws_matched.Range(Cells(a, 1).Address, Cells(a, 14).Address)
ws_rinternal.Range(Cells(b, 1).Address, Cells(b, 14).Address).Copy Destination:=ws_matched.Range(Cells(a, 16).Address, Cells(a, 30).Address)
ws_matched.Cells(a, 15).Value = "Matched"
ws_matched.Cells(a, 15).Interior.Color = RGB(0, 255, 0)
ws_rexternal.Rows(a).ClearContents
ws_rinternal.Rows(b).ClearContents
End If
Next b
Next a
'reformat the unmatched and matched
For d = ex_LR To 1 Step -1
Set ex_Row = ws_rexternal.Rows(d)
If WorksheetFunction.CountA(ex_Row) = 0 Then
ws_rexternal.Rows(d).Delete
End If
Next d
For e = in_LR To 1 Step -1
Set in_Row = ws_rinternal.Rows(e)
If WorksheetFunction.CountA(in_Row) = 0 Then
ws_rinternal.Rows(e).Delete
End If
Next e
report_exLR = ws_rexternal.Cells(Rows.Count, 2).End(xlUp).Row
report_inLR = ws_rinternal.Cells(Rows.Count, 2).End(xlUp).Row
Set report_exrng = ws_rexternal.Range("A1:A" & report_exLR)
report_exrng.EntireRow.Copy ws_unmatched.Cells(1, 1)
Set report_inrng = ws_rinternal.Range("A1:A" & report_inLR)
report_inrng.EntireRow.Copy ws_unmatched.Cells(ex_LR, 1).Offset(5, 0)
End Sub
Ok this is probably a lot more complex than it needs to be, but it seems to work OK.
It would be much simpler to just flag the data in-place as matched/unmatched, with a pointer to the matching row on the other sheet.
Sub FormatExcel()
Dim report_exLR As Long, ws_rexternal As Worksheet, ws_unmatched As Worksheet
Dim report_inLR As Long, ws_rinternal As Worksheet, ws_matched As Worksheet
Dim report_exrng As Range, report_inrng As Range
Dim rngInt As Range, rngExt As Range, k, rw As Range, t, rwMatch As Long
Dim rngIntKeys As Range, rngExtKeys As Range, m, rng As Range, n As Long
Dim rngUnmatchedInt As Range, rngUnmatchedExt As Range
Setup
t = Timer
With ThisWorkbook
Set ws_rexternal = .Worksheets("Reformat External")
Set ws_rinternal = .Worksheets("Reformat Internal")
Set ws_unmatched = .Worksheets("Unmatched")
Set ws_matched = .Worksheets("Matched")
End With
'clear previous data
ws_unmatched.Cells.Clear
ws_matched.Cells.Clear
'source data ranges
Set rngInt = ws_rinternal.Range("A2:M" & ws_rinternal.Cells(Rows.Count, 2).End(xlUp).Row)
Set rngExt = ws_rexternal.Range("A2:M" & ws_rexternal.Cells(Rows.Count, 2).End(xlUp).Row)
'speed up copy/paste
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
'generate all keys for Internal rows in ColT
For Each rw In rngInt.Rows
rw.EntireRow.Columns("T").Value = RowKey(rw)
Next rw
Set rngIntKeys = rngInt.EntireRow.Columns("T") 'range with keys
Debug.Print "Generated keys", Timer - t
rwMatch = 1
For Each rw In rngExt.Rows
If rw.Row Mod 100 = 0 Then Debug.Print "Row: " & rw.Row, Timer - t
m = Application.Match(RowKey(rw), rngIntKeys, 0)
If Not IsError(m) Then 'got match on "internal" sheet?
rwMatch = rwMatch + 1
rw.Copy ws_matched.Cells(rwMatch, "A")
ws_matched.Cells(rwMatch, "N").Value = "Matched"
rngInt.Rows(m).Copy ws_matched.Cells(rwMatch, "P")
rngIntKeys.Cells(m).ClearContents 'remove matched key from T
Else
BuildRange rngUnmatchedExt, rw 'collect unmatched external row
End If
Next rw
Debug.Print "Copied matches", Timer - t
'copy unmatched external
If Not rngUnmatchedExt Is Nothing Then
rngUnmatchedExt.Copy ws_unmatched.Range("A1")
End If
'copy unmatched internal
Set rngIntKeys = rngInt.EntireRow.Columns("T")
For n = 1 To rngExt.Rows.Count
If Len(rngIntKeys.Cells(n).Value) > 0 Then
BuildRange rngUnmatchedInt, rngExt.Rows(n)
End If
Next n
If Not rngUnmatchedInt Is Nothing Then
rngUnmatchedInt.Copy _
ws_unmatched.Cells(ws_unmatched.UsedRange.Rows.Count + 5, 1)
End If
Debug.Print "Copied non-matches", Timer - t
Application.Calculation = xlCalculationAutomatic
End Sub
'generate a "key" by concatenating all cell values in `rng` with "|"
Function RowKey(rng As Range) As String
RowKey = Join(Application.Transpose(Application.Transpose(rng.Value)), "|")
End Function
'build up a range from sub-ranges
Sub BuildRange(ByRef rngTot As Range, rngAdd As Range)
If rngTot Is Nothing Then
Set rngTot = rngAdd
Else
Set rngTot = Application.Union(rngTot, rngAdd)
End If
End Sub
For completeness here's the sub I used to reset the sheets and create sample data:
'reset the sheets and create some sample data
Sub Setup()
Const ROWSN As Long = 1000 '# of rows to create
Const RNDV As String = "=ROUND(rand()*5,0)" 'adjust to change chance of matched rows
Dim ws_rexternal As Worksheet, ws_unmatched As Worksheet
Dim ws_rinternal As Worksheet, ws_matched As Worksheet
With ThisWorkbook
Set ws_rexternal = .Worksheets("Reformat External")
Set ws_rinternal = .Worksheets("Reformat Internal")
Set ws_unmatched = .Worksheets("Unmatched")
Set ws_matched = .Worksheets("Matched")
End With
'clar all sheets
ws_unmatched.Cells.Clear
ws_matched.Cells.Clear
ws_rexternal.Cells.Clear
ws_rinternal.Cells.Clear
'ws_rexternal.Range ("A2:M1000")
With ws_rexternal.Range("A2:C2").Resize(ROWSN)
.Formula = RNDV
.Value = .Value
End With
ws_rexternal.Range("D2:M2").Resize(ROWSN).Value = "blah"
With ws_rinternal.Range("A2:C2").Resize(ROWSN)
.Formula = RNDV
.Value = .Value
End With
ws_rinternal.Range("D2:M2").Resize(ROWSN).Value = "blah"
End Sub

For each loop to go to next row in iteration once value found in range

All,
I have the below code which iterates through columns and rows to see IF the statement is true. It seems to be running through the whole code bringing back duplicate rows. I would like this code to go to the next row once a value has been found.
I'm unsure how to adapt this code but I imagine the issue lies with the general for each loop I have set up any advise on how to fix this would be much appreciated.
Dim LR As Long
LR = Workbooks(trackerName).Sheets("Results").Range("A1048576").End(xlUp).Row
Dim LRC As Long
LRC = Workbooks(trackerName).Sheets("Columnsforbox").Range("A1048576").End(xlUp).Row + 1
For Each c In Workbooks(trackerName).Sheets("results").Range("A4:K" & LR)
If c.Value = UserName Or c.Value = UserId Then
Worksheets("Columnsforbox").Range("A" & LRC) = Worksheets("Results").Range("E" & c.Row)
Worksheets("Columnsforbox").Range("B" & LRC) = Worksheets("Results").Range("D" & c.Row)
Worksheets("Columnsforbox").Range("C" & LRC) = Worksheets("Results").Range("A" & c.Row)
Worksheets("Columnsforbox").Range("D" & LRC) = Worksheets("Results").Range("B" & c.Row)
Worksheets("Columnsforbox").Range("E" & LRC) = Worksheets("Results").Range("C" & c.Row)
LRC = LRC + 1
End If
Next c
Basicly the same, but now we loop through array:
Dim myArr(), i as Long, j as Long
Dim LR As Long
LR = Workbooks(trackerName).Sheets("Results").Range("A1048576").End(xlUp).Row
Dim LRC As Long
LRC = Workbooks(trackerName).Sheets("Columnsforbox").Range("A1048576").End(xlUp).Row + 1
myArr = Range("A4:K" & LR).Value
For i = LBound(myArr,1) To Ubound(myArr,1)
For j = LBound(myArr,2) To Ubound(myArr,2)
If myArr(i,j) = UserName Or myArr(i,j) = UserId Then
Worksheets("Columnsforbox").Range("A" & LRC) = Worksheets("Results").Range("E" & i)
Worksheets("Columnsforbox").Range("B" & LRC) = Worksheets("Results").Range("D" & i)
Worksheets("Columnsforbox").Range("C" & LRC) = Worksheets("Results").Range("A" & i)
Worksheets("Columnsforbox").Range("D" & LRC) = Worksheets("Results").Range("B" & i)
Worksheets("Columnsforbox").Range("E" & LRC) = Worksheets("Results").Range("C" & i)
LRC = LRC + 1
Exit For
End If
Next j
Next i
Well, you got an idea.
Another solution without using loop.
Sub Demo()
Dim rngUserName As Range, rngUserId As Range
Dim LR As Long, LRC As Long, rowIndex As Long
Dim srcSht As Worksheet, destSht As Worksheet
Set srcSht = Workbooks(trackerName).Sheets("Results") 'this is source sheet
Set destSht = Workbooks(trackerName).Sheets("Columnsforbox") 'this is destination sheet
LR = srcSht.Cells(srcSht.Rows.Count, "A").End(xlUp).Row 'get last row using column A
LRC = destSht.Cells(destSht.Rows.Count, "A").End(xlUp).Row 'get last row using column A
Set rngUserName = Range("A4:K" & LR).Find(UserName, after:=Cells(4, 1), searchdirection:=xlPrevious) 'find user name
Set rngUserId = Range("A4:K" & LR).Find(UserId, after:=Cells(4, 1), searchdirection:=xlPrevious) 'find user id
If Not rngUserName Is Nothing And Not rngUserId Is Nothing Then 'if both user name & user id are found
rowIndex = Application.Max(rngUserName.Row, rngUserId.Row)
ElseIf Not rngUserName Is Nothing Then 'if only user name found
rowIndex = rngUserName.Row
ElseIf Not Not rngUserId Is Nothing Then 'if only user id found
rowIndex = rngUserId.Row
End If
MsgBox rowIndex
destSht.Range("A" & LRC) = srcSht.Range("E" & rowIndex)
destSht.Range("B" & LRC) = srcSht.Range("D" & rowIndex)
destSht.Range("C" & LRC) = srcSht.Range("A" & rowIndex)
destSht.Range("D" & LRC) = srcSht.Range("B" & rowIndex)
destSht.Range("E" & LRC) = srcSht.Range("C" & rowIndex)
End Sub

How to end this loop?

I currently have a VBA Code written to ask for a users input of a string as well as a certain directory, and it searches through each folder, subfolder, workbook and worksheets until it finds the string the user put in. The issue I'm running into is that after it finds the string, it continues to search the rest of the folders. The application I'll be using this in, there is only one of that string being searched. I have tried debugging, and using an if statement with "c" to match str but it keeps throwing an error. The code is attached below, any help is appreciated.
Public WS As Worksheet
Sub SearchWKBooksSubFolders(Optional Folderpath As Variant, Optional Str As Variant)
Dim myfolder As String
Dim a As Single
Dim sht As Worksheet
Dim Lrow As Single
Dim Folders() As String
Dim Folder As Variant
ReDim Folders(0)
If IsMissing(Folderpath) Then
Set WS = Sheets.Add
With Application.FileDialog(msoFileDialogFolderPicker)
.Show
myfolder = .SelectedItems(1) & "\"
End With
Str = Application.InputBox(prompt:="Search string:", Title:="Search all workbooks in a folder", Type:=2)
If Str = "" Then Exit Sub
WS.Range("A1") = "Search string:"
WS.Range("B1") = Str
WS.Range("A2") = "Path:"
WS.Range("B2") = myfolder
WS.Range("A3") = "Folderpath"
WS.Range("B3") = "Workbook"
WS.Range("C3") = "Worksheet"
WS.Range("D3") = "Cell Address"
WS.Range("E3") = "Link"
Folderpath = myfolder
Value = Dir(myfolder, &H1F)
Else
If Right(Folderpath, 2) = "\\" Then
Exit Sub
End If
Value = Dir(Folderpath, &H1F)
End If
Do Until Value = ""
If Value = "." Or Value = ".." Then
Else
If GetAttr(Folderpath & Value) = 16 Then
Folders(UBound(Folders)) = Value
ReDim Preserve Folders(UBound(Folders) + 1)
ElseIf (Right(Value, 3) = "xls" Or Right(Value, 4) = "xlsx" Or Right(Value, 4) = "xlsm") And Left(Value, 1) <> "~" Then
On Error Resume Next
Dim wb As Workbook
Set wb = Workbooks.Open(Filename:=Folderpath & Value, Password:="zzzzzzzzzzzz")
On Error GoTo 0
'If there is an error on Workbooks.Open, then wb Is Nothing:
If wb Is Nothing Then
Lrow = WS.Range("A" & Rows.Count).End(xlUp).Row + 1
WS.Range("A" & Lrow).Value = Value
WS.Range("B" & Lrow).Value = "Password protected"
Else
For Each sht In wb.Worksheets
'Expand all groups in sheet
sht.Unprotect
sht.Outline.ShowLevels RowLevels:=8, ColumnLevels:=8
Set c = sht.Cells.Find(Str, After:=sht.Cells(1, 1), LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext)
If Not c Is Nothing Then
firstAddress = c.Address
Do
Lrow = WS.Range("A" & Rows.Count).End(xlUp).Row + 1
WS.Range("A" & Lrow).Value = Folderpath
WS.Range("B" & Lrow).Value = Value
WS.Range("C" & Lrow).Value = sht.Name
WS.Range("D" & Lrow).Value = c.Address
WS.Hyperlinks.Add Anchor:=WS.Range("E" & Lrow), Address:=Folderpath & Value, SubAddress:= _
"'" & sht.Name & "'" & "!" & c.Address, TextToDisplay:="Link"
Set c = sht.Cells.FindNext(After:=c)
Loop While Not c Is Nothing And c.Address <> firstAddress
End If
Next sht
wb.Close False
End If
End If
End If
Value = Dir
Loop
For Each Folder In Folders
Call SearchWKBooksSubFolders(Folderpath & Folder & "\", Str)
Next Folder
Cells.EntireColumn.AutoFit
End Sub
Add a boolean variable that you set to True to indicate that you've found what you're looking for. Something like this:
Sub SearchWKBooksSubFolders(Optional Folderpath As Variant, Optional Str As Variant)
Dim myfolder As String
Dim a As Single
Dim sht As Worksheet
Dim Lrow As Single
Dim Folders() As String
Dim Folder As Variant
ReDim Folders(0)
If IsMissing(Folderpath) Then
Set WS = Sheets.Add
With Application.FileDialog(msoFileDialogFolderPicker)
.Show
myfolder = .SelectedItems(1) & "\"
End With
Str = Application.InputBox(prompt:="Search string:", Title:="Search all workbooks in a folder", Type:=2)
If Str = "" Then Exit Sub
WS.Range("A1") = "Search string:"
WS.Range("B1") = Str
WS.Range("A2") = "Path:"
WS.Range("B2") = myfolder
WS.Range("A3") = "Folderpath"
WS.Range("B3") = "Workbook"
WS.Range("C3") = "Worksheet"
WS.Range("D3") = "Cell Address"
WS.Range("E3") = "Link"
Folderpath = myfolder
value = Dir(myfolder, &H1F)
Else
If Right(Folderpath, 2) = "\\" Then
Exit Sub
End If
value = Dir(Folderpath, &H1F)
End If
'---Add this:
Dim TimeToStop As Boolean
'---Change this:
Do Until TimeToStop
If value = "." Or value = ".." Then
Else
If GetAttr(Folderpath & value) = 16 Then
Folders(UBound(Folders)) = value
ReDim Preserve Folders(UBound(Folders) + 1)
ElseIf (Right(value, 3) = "xls" Or Right(value, 4) = "xlsx" Or Right(value, 4) = "xlsm") And Left(value, 1) <> "~" Then
On Error Resume Next
Dim wb As Workbook
Set wb = Workbooks.Open(fileName:=Folderpath & value, Password:="zzzzzzzzzzzz")
On Error GoTo 0
'If there is an error on Workbooks.Open, then wb Is Nothing:
If wb Is Nothing Then
Lrow = WS.Range("A" & Rows.Count).End(xlUp).Row + 1
WS.Range("A" & Lrow).value = value
WS.Range("B" & Lrow).value = "Password protected"
Else
For Each sht In wb.Worksheets
'Expand all groups in sheet
sht.Unprotect
sht.Outline.ShowLevels RowLevels:=8, ColumnLevels:=8
Set c = sht.Cells.Find(Str, After:=sht.Cells(1, 1), LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext)
If Not c Is Nothing Then
'---Add this
TimeToStop = True 'since we found what we're looking for
firstAddress = c.Address
Do
Lrow = WS.Range("A" & Rows.Count).End(xlUp).Row + 1
WS.Range("A" & Lrow).value = Folderpath
WS.Range("B" & Lrow).value = value
WS.Range("C" & Lrow).value = sht.Name
WS.Range("D" & Lrow).value = c.Address
WS.Hyperlinks.Add Anchor:=WS.Range("E" & Lrow), Address:=Folderpath & value, SubAddress:= _
"'" & sht.Name & "'" & "!" & c.Address, TextToDisplay:="Link"
Set c = sht.Cells.FindNext(After:=c)
Loop While Not c Is Nothing And c.Address <> firstAddress
End If
Next sht
wb.Close False
End If
End If
End If
value = Dir
'---Add these 3 lines
If Len(value) = 0 Then
TimeToStop = True
End If
Loop
For Each Folder In Folders
Call SearchWKBooksSubFolders(Folderpath & Folder & "\", Str)
Next Folder
Cells.EntireColumn.AutoFit
End Sub
Do note that you're calling your routine recursively:
For Each Folder In Folders
Call SearchWKBooksSubFolders(Folderpath & Folder & "\", Str)
Next Folder
Once you've gone through all your searching routine, you're going to start all over again because you're calling your Sub from within your Sub. Don't know if this is what you're after, and it may be an additional cause of further unexpected looping.
"If Str = c.Value Then GoTo 85"
Change to
"If Str = c.Value Then End"

Need a real VBA equivalent for Excel Value function

As mentioned in the title, I need a VBA equivalent to the Excel Value function. My data set looks like this: Data set example
What I am looking for is VBA code equivalent to this: =Value(A2)+Value(B2). That would go in column C
The output must be the same as that function. For the given example, column C should end up looking like this: End product
More than that, it needs to only have the value in the cell after the macro is run, rather than displaying the value and still having that formula in it.
Here is what I have done so far:
For i = 1 To LastRow
strValue = Val(sht.Range("A" & i))
strValue1 = Val(sht.Range("B" & i))
sht.Range("C" & i).Value = strValue + strValue1
Next i
I also tried variations on this, a couple of which are shown below:
For i = 1 To LastRow
strValue = Evaluate(sht.Range("A" & i))
strValue1 = Evaluate(sht.Range("B" & i))
sht.Range("C" & i).Value = strValue + strValue1
Next i
For i = 1 To LastRow
strValue = sht.Range("A" & i)
strValue1 = sht.Range("B" & i)
strVal = Evaluate(strValue)
strVal1 = Evaluate(strValue1)
sht.Range("C" & i).Value = strVal + strVal1
Next i
I can't find anything that will work for me. The output in C for the example set ends up being just 9. Pretty sure it is taking the first number in A and adding it to the first number in B. So when the hour in B changes to 1 C displays 10.
I also tried simply:
For i=1 To LastRow
sht.Range("C" & i).Value = sht.Range("A" & i).Value + sht.Range("B" & i).Value
Next i
That just concatenated the text to the format 9/03/15 00:00:00
Any and all help appreciated. Bonus if you can point me in the right direction for changing the final C values from that number (ie. 42250.00017) to the custom date/time format 'yyyy-mm-dd hh:mm:ss'.
Edit: Here is my code up to the sticking point. Everything else works as I want it to, the only problem is with the last For loop.
Sub sbOrganizeData()
Dim i As Long
Dim k As Long
Dim sht As Worksheet
Dim LastRow As Long
Dim sFound As String
Dim rng As Range
Dim sheet As Worksheet
Dim Sheet2 As Worksheet
Dim strFile As String
Dim strCSV As String
Dim strValue As Double
Dim strValue1 As Double
Dim strVal As Long
Dim strVal1 As Long
Application.DisplayAlerts = False
Sheets("all016").Delete
Sheets("Sheet1").Delete
Application.DisplayAlerts = True
Set sheet = Sheets.Add
Set Sheet2 = Sheets.Add
sheet.Name = "all016"
Sheet2.Name = "Sheet1"
strFile = ActiveWorkbook.Path
strCSV = "*.csv"
sFound = Dir(strFile & "\*.csv")
If sFound <> "" Then
Workbooks.Open Filename:=strFile & "\" & sFound
End If
Range("A1").CurrentRegion.Copy Destination:=Workbooks("solar.xlsm").Sheets("all016").Range("A1")
Workbooks(sFound).Close
Set sht = ThisWorkbook.Sheets("all016")
LastRow = sht.Cells.Find("*", searchorder:=xlByRows, searchdirection:=xlPrevious).Row
sht.Range("C1").EntireColumn.Insert
For i = 1 To LastRow
'Code that doesn't quite work here'
sht.Range("C" & i).NumberFormat = "yyyy-mm-dd hh:mm:ss"
Next i
The issue is that the dates and times are strings so something like this will work:
For i = 2 To LastRow
strValue = Evaluate("VALUE(TRIM(" & sht.Range("A" & i).Address(1,1,,1) & "))")
strValue1 = Evaluate("VALUE(TRIM(" & sht.Range("B" & i).Address(1,1,,1) & "))")
sht.Range("C" & i).Value = strValue + strValue1
'the format
sht.Range("C" & i).NumberFormat = "mm/dd/yy hh:mm:ss"
Next i
You have to reference the .Value2 field of the range element as:
For i = 1 To LastRow
sht.Range("C" & i).Value2 = sht.Range("A" & i).Value2 + sht.Range("B" & i).Value2
Next i
The value is free of formatting and just in Excel's time/date code as you want your final result to be. Cheers,

Find matching cell with different strings inside one cell

My goal of my macro:
I have 2 sheets, sheet1 master report and sheet2 import Input.
In column A of both sheets I have several strings in one cell.
I would like to see if there is a match and if there is the match the row from sheet2 (from column B) will be copied and paste in the row corresponding in sheet1.
This part of my code is done.
But now it starts to be tricky: If there is new string in the same cell as the matching string so I would like to add them as well in the cell of the column A sheet1.
For instance:
Sheet1 Column A Cell34:
MDM-9086
Sheet2 Column A Cell1:
MDM-9086,MDM-12345
After the macro it would be like this:
Sheet1 Column A cell34:
MDM-9086,MDM-12345
If there is no match between column A of both sheets so I would like to copy the entire row of the sheet2 and past it in the last free row of the sheet1.
See my code:
Sub MDMNumbers()
Dim LastRw1 As Long, LastRw2 As Long, NxtRw As Long
Dim I As Integer
Dim m As Range
Dim Tb
LastRw1 = Sheets(1).Range("A" & Rows.Count).End(xlUp).Row
LastRw2 = Sheets(2).Range("A" & Rows.Count).End(xlUp).Row
With Worksheets(2)
LastRw2 = .Range("A" & Rows.Count).End(xlUp).Row
For NxtRw = 2 To LastRw2
Tb = Split(.Range("A" & NxtRw), ",")
For I = 0 To UBound(Tb)
With Sheets(1).Range("A2:A" & LastRw1)
Set m = .Find(Trim(Tb(I)), LookAt:=xlPart)
If Not m Is Nothing Then
Sheets(2).Range("B" & NxtRw & ":Q" & NxtRw).Copy _
Sheets(1).Range("B" & m.Row)
Set m = Nothing
End If
End With
Next I
Next NxtRw
End With
End Sub
Example:
Sheet 1, Column A (start row 2)
MDM-123,MDM-27827
MDM-1791728,MDM-124
MDM-125
MDM-126,MDM-28920
MDM-127,MDM-1008
""
Sheet 2, Column A (start row 2)
MDM-123,MDM-27272
MDM-124
MDM-125,MDM-1289
MDM-126
MDM-1008
MDM-127
MDM-172891
Result on Sheet 1, Column A (start row 2):
MDM-123,MDM-27827,MDM-27272
MDM-124,MDM-1791728
MDM-125,MDM-1289
MDM-126,MDM-28920
MDM-127,MDM-1008
MDM-1008
MDM-172891
For your # 2.
Option Explicit
Public Sub MDMNumbers()
Dim LastRw1 As Long, LastRw2 As Long, NxtRw As Long, rng1 As Range, rng2 As Range
Dim i As Long, m As Range, tb() As String, celVal As String, notFound As Boolean
Dim additions1 As String, additions2 As String
LastRw1 = Worksheets(1).Range("A" & Worksheets(1).Rows.Count).End(xlUp).Row + 1
LastRw2 = Worksheets(2).Range("A" & Worksheets(2).Rows.Count).End(xlUp).Row
notFound = True
For NxtRw = 2 To LastRw2
celVal = Worksheets(2).Range("A" & NxtRw).Value2
If Len(celVal) > 0 Then
tb = Split(celVal, ",")
For i = 0 To UBound(tb)
Set m = Worksheets(1).Columns(1).Find(Trim(tb(i)), LookAt:=xlPart)
If Not m Is Nothing And notFound Then
Set rng1 = Worksheets(2).Range("B" & NxtRw & ":Q" & NxtRw)
Set rng2 = Worksheets(1).Range("B" & m.Row & ":Q" & m.Row)
rng1.Copy rng2
With Worksheets(2).Range("A" & NxtRw)
additions1 = Replace(.Value2, "," & tb(i), vbNullString)
additions1 = Replace(additions1, tb(i) & ",", vbNullString)
additions1 = Replace(additions1, tb(i), vbNullString)
End With
With Worksheets(1).Range("A" & m.Row)
additions2 = Replace(.Value2, "," & tb(i), vbNullString)
additions2 = Replace(additions2, tb(i) & ",", vbNullString)
additions2 = Replace(additions2, tb(i), vbNullString)
If Len(additions2) > 0 Then
If Len(additions1) > 0 Then
.Value2 = tb(i) & "," & additions2 & "," & additions1
Else
.Value2 = tb(i) & "," & additions2
End If
Else
.Value2 = tb(i) & "," & additions1
End If
End With
Set m = Nothing
notFound = False
End If
Next
If notFound Then
Set rng1 = Worksheets(2).Range("A" & NxtRw & ":Q" & NxtRw)
Set rng2 = Worksheets(1).Range("A" & LastRw1 & ":Q" & LastRw1)
rng1.Copy rng2
LastRw1 = LastRw1 + 1
End If
notFound = True
End If
Next
End Sub
It should work as expected now
Test data and result:
Why don't you copy the whole row from sheet2 to sheet1 like
For NxtRw = 2 To LastRw2
...
Sheets(2).Range("A" & NxtRw & ":Q" & NxtRw).Copy _
Sheets(1).Range("A" & m.Row)
...
Next NxtRw
? (The rest of the loop should stay the same.)