Macro creating a new workbork instead of adding a sheet - excel

The following Macro was intended to get specific data for a date range. While it does this, I wanted it displayed within the same workbook on another sheet, instead a new workbook is created. Any idea on how I can fix this?
Public Sub PromptUserForInputDates()
Dim strStart As String, strEnd As String, strPromptMessage As String
strStart = InputBox("Please enter the start date")
If Not IsDate(strStart) Then
strPromptMessage = "Not Valid Date"
MsgBox strPromptMessage
Exit Sub
End If
strEnd = InputBox("Please enter the end date")
If Not IsDate(strStart) Then
strPromptMessage = "Not Valid Date"
MsgBox strPromptMessage
Exit Sub
End If
Call CreateSubsetWorkbook(strStart, strEnd)
End Sub
Public Sub CreateSubsetWorkbook(StartDate As String, EndDate As String)
Dim wbkOutput As Workbook
Dim wksOutput As Worksheet, wks As Worksheet
Dim lngLastRow As Long, lngLastCol As Long, lngDateCol As Long
Dim rngFull As Range, rngResult As Range, rngTarget As Range
lngDateCol = 4
Set wbkOutput = Workbooks.Add
For Each wks In ThisWorkbook.Worksheets
With wks
Set wksOutput = wbkOutput.Sheets.Add
wksOutput.Name = wks.Name
Set rngTarget = wksOutput.Cells(1, 1)
lngLastRow = .Cells.Find(What:="*", LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious).Row
lngLastCol = .Cells.Find(What:="*", LookIn:=xlFormulas, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious).Column
Set rngFull = .Range(.Cells(1, 1), .Cells(lngLastRow, lngLastCol))
With rngFull
.AutoFilter Field:=lngDateCol, _
Criteria1:=">=" & StartDate, _
Criteria2:="<=" & EndDate
Set rngResult = rngFull.SpecialCells(xlCellTypeVisible)
rngResult.Copy Destination:=rngTarget
End With
.AutoFilterMode = False
If .FilterMode = True Then
.ShowAllData
End If
End With
Next wks
MsgBox "Data Transferred!"
End Sub

You're defining Set wbkOutput = Workbooks.Add which will always create a new workbook. Instead, Set wbkOutput = the workbook where you want the output to be.
Note that your assignment of wksOutput.Name = wks.Name will fail (two worksheets cannot have same name), so I've commented it out for now and you can revise that statement as needed.
Replace all references to wbkOutput with ThisWorkbook
Public Sub CreateSubsetWorkbook(StartDate As String, EndDate As String)
Dim wksOutput As Worksheet, wks As Worksheet
Dim lngLastRow As Long, lngLastCol As Long, lngDateCol As Long
Dim rngFull As Range, rngResult As Range, rngTarget As Range
lngDateCol = 4
For Each wks In ThisWorkbook.Worksheets
With wks
Set wksOutput = ThisWorkbook.Sheets.Add
' This is not allowed, you can make some change to the name but it cannot be the same name worksheet
' >>> wksOutput.Name = wks.Name
Set rngTarget = wksOutput.Cells(1, 1)
lngLastRow = .Cells.Find(What:="*", LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious).Row
lngLastCol = .Cells.Find(What:="*", LookIn:=xlFormulas, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious).Column
Set rngFull = .Range(.Cells(1, 1), .Cells(lngLastRow, lngLastCol))
With rngFull
.AutoFilter Field:=lngDateCol, _
Criteria1:=">=" & StartDate, _
Criteria2:="<=" & EndDate
Set rngResult = rngFull.SpecialCells(xlCellTypeVisible)
rngResult.Copy Destination:=rngTarget
End With
.AutoFilterMode = False
If .FilterMode = True Then
.ShowAllData
End If
End With
Next wks
End Sub

Related

VBA loop selection.find

I want to loop or find multiple value in another sheets. My code doesn't work even after I do..loop the code.
For i = 1 To lastrowBAU
Worksheets(fname).Range("A1:A" & lastrowsheet).Select
Do Until Cell Is Nothing
Set Cell = Selection.find(What:=ThisWorkbook.Worksheets("BAU").Range("A" & i).Value, After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, _
MatchCase:=False)
If Not Cell Is Nothing Then
Cell.Activate
ActiveCell.Copy
ActiveCell.Insert Shift:=xlShiftDown
ActiveCell.Offset(1, 0).Select
Selection.Replace What:=ThisWorkbook.Worksheets("BAU").Range("A" & i).Value, _
replacement:=ThisWorkbook.Worksheets("BAU").Range("B" & i).Value, _
LookAt:=xlPart, SearchOrder:=xlByRows, MatchCase:=False
Set Cell = Worksheets(fname).Range("A1:A" & lastrowsheet).FindNext(Cell)
End If
Loop
Next i
You need to set the cell before entering the loop
Set cell = rngSrc.Find(sA, LookIn:=xlFormulas, LookAt:=xlPart, _
After:=rngSrc.Cells(rngSrc.Cells.Count), SearchOrder:=xlByRows, MatchCase:=False)
If Not cell Is Nothing Then
however you also need to avoid an endless loop by checking if the search has returned to the first one found.
Option Explicit
Sub macro1()
Dim ws As Worksheet, wsBAU As Worksheet
Dim cell As Range, rngSrc As Range
Dim fname As String, lastrow As Long, lastrowBAU As Long
Dim i As Long, n As Long, first As String
Dim sA As String, sB As String
fname = "Sheet1"
With ThisWorkbook
Set ws = .Sheets(fname)
Set wsBAU = .Sheets("BAU")
End With
With ws
lastrow = .Cells(.Rows.Count, "A").End(xlUp).Row
Set rngSrc = .Range("A1:A" & lastrow)
End With
With wsBAU
lastrowBAU = .Cells(.Rows.Count, "A").End(xlUp).Row
End With
With ws
lastrow = .Cells(.Rows.Count, "A").End(xlUp).Row
Set rngSrc = .Range("A1:A" & lastrow)
End With
' search and replace
Application.ScreenUpdating = False
For i = 1 To lastrowBAU
sA = wsBAU.Cells(i, "A")
sB = wsBAU.Cells(i, "B")
Set cell = rngSrc.Find(sA, LookIn:=xlFormulas, LookAt:=xlPart, _
After:=rngSrc.Cells(rngSrc.Cells.Count), SearchOrder:=xlByRows, MatchCase:=False)
If Not cell Is Nothing Then
first = cell.Address
Do
' insert cell above
cell.Insert xlDown
cell.Offset(-1).Value2 = cell.Value2
cell.Value2 = Replace(cell.Value2, sA, sB)
' expand search range
n = n + 1
Set rngSrc = ws.Range("A1:A" & lastrow + n)
' find next
Set cell = rngSrc.FindNext(cell)
Loop While cell.Address <> first
End If
Next
Application.ScreenUpdating = True
MsgBox n & " replacements", vbInformation
End Sub

Macro Stops Working After First Run - Run-time Error 2004 Application-defined or Object-defined error

I am trying to put together a macro that finds a name in a column header then copies that column if the header matches.
It works the first time I run it but when the pasted column is deleted and the macro is run again I get a
Run-time Error 2004 Application-defined or Object-defined error
on this line:
Set sRange = Sheets("Data").Range("C1", Cells(1, LastCol))
Full code:
Sub Copy()
Dim Cell As Range, sRange As Range, Rng As Range
LastCol = Sheets("Data").Cells(1, Columns.Count).End(xlToLeft).Column
Set sRange = Sheets("Data").Range("C1", Cells(1, LastCol))
With sRange
Set Rng = .Find(What:="Chennai", _
After:=.Cells(1), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False)
If Not Rng Is Nothing Then
Lastrow = Sheets("Data").Cells(Rows.Count, Rng.Column).End(xlUp).Row
Sheets("Data").Range(Rng, Cells(Lastrow, Rng.Column)).Copy _
Destination:=Sheets("Summary").Range("A7")
End If
End With
End Sub
Can anyone see the issue?
Cells(1, LastCol)) has no worksheet specified. Therfore it is the same as ActiveSheet.Cells(1, LastCol)) and if Sheets("Data") is not the ActiveSheet this fails.
It should be
Set sRange = Worksheets("Data").Range("C1", Worksheets("Data").Cells(1, LastCol))
or even better
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Data")
Set sRange = ws.Range("C1", ws.Cells(1, LastCol))
Also I recommend to use Worksheets for worksheets as Sheets can also contain chart sheets etc.
Same problem in the end where Cells(Lastrow, Rng.Column) has no worksheet specified:
ws.Range(Rng, ws.Cells(Lastrow, Rng.Column)).Copy _
Destination:=Worksheets("Summary").Range("A7")
Make sure you never have a Cells, Range, Rows or Columns object without a worksheet specified. Or Excel might take the wrong worksheet.
In the end I would do something like (note that all variables should be declared, use Option Explicit:
Option Explicit
Public Sub Copy()
Dim wsSrc As Worksheet 'source worksheet
Set wsSrc = ThisWorkbook.Worksheets("Data")
Dim wsDest As Worksheet 'destination worksheet
Set wsDest = ThisWorkbook.Worksheets("Summary")
Dim LastCol As Long
LastCol = wsSrc.Cells(1, wsSrc.Columns.Count).End(xlToLeft).Column
Dim sRange As Range
Set sRange = wsSrc.Range("C1", wsSrc.Cells(1, LastCol))
Dim Rng As Range
Set Rng = sRange.Find(What:="Chennai", _
After:=sRange.Cells(1), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False)
If Not Rng Is Nothing Then
Dim LastRow As Long
LastRow = wsSrc .Cells(wsSrc.Rows.Count, Rng.Column).End(xlUp).Row
wsSrc.Range(Rng, wsSrc.Cells(LastRow, Rng.Column)).Copy _
Destination:=wsDest.Range("A7")
End If
End Sub

VBA to Paste as value and loop through specific sheets

I need my code to copy and paste values from only 2 specific sheets "Pro Rate" & "Weekly Labor" These two sheets have the same 9 columns that I want copied over.
The problem is my code is copying all 20+ sheets and pasting with formulas so essentially I get all NAs
I've tried using a code:
Public Sub CombineDataFromAllSheets()
Dim wksSrc As Worksheet, wksDst As Worksheet
Dim rngSrc As Range, rngDst As Range
Dim lngLastCol As Long, lngSrcLastRow As Long, lngDstLastRow As Long
'Notes: "Src" is short for "Source", "Dst" is short for "Destination"
Set wksDst = ThisWorkbook.Worksheets("Import")
lngDstLastRow = LastOccupiedRowNum(wksDst)
Set rngDst = wksDst.Cells(2, 1)
For Each wksSrc In ThisWorkbook.Worksheets
If wksSrc.Name <> "Import" Then
lngSrcLastRow = LastOccupiedRowNum(wksSrc)
With wksSrc
Set rngSrc = .Range(.Cells(2, 1), .Cells(lngSrcLastRow, 9))
rngSrc.Copy Destination:=rngDst
End With
lngDstLastRow = LastOccupiedRowNum(wksDst)
Set rngDst = wksDst.Cells(lngDstLastRow + 1, 1)
End If
Next wksSrc
End Sub
Public Function LastOccupiedRowNum(Sheet As Worksheet) As Long
Dim lng As Long
If Application.WorksheetFunction.CountA(Sheet.Cells) <> 0 Then
With Sheet
lng = .Cells.Find(What:="*", _
After:=.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
End With
Else
lng = 1
End If
LastOccupiedRowNum = lng
End Function
First, you need to run a check to make sure that the sheet names match the ones you want to copy.
Second you need to use .PasteSpecial to ensure only values are pasted.
I have updated only the above 2 things in your code below...
Public Sub CombineDataFromAllSheets()
Dim wksSrc As Worksheet, wksDst As Worksheet
Dim rngSrc As Range, rngDst As Range
Dim lngLastCol As Long, lngSrcLastRow As Long, lngDstLastRow As Long
'Notes: "Src" is short for "Source", "Dst" is short for "Destination"
Set wksDst = ThisWorkbook.Worksheets("Import")
lngDstLastRow = LastOccupiedRowNum(wksDst)
Set rngDst = wksDst.Cells(2, 1)
For Each wksSrc In ThisWorkbook.Worksheets
'first change here**
If wksSrc.Name = "Pro Rate" Or wksSrc.Name = "Weekly Labor" Then
lngSrcLastRow = LastOccupiedRowNum(wksSrc)
With wksSrc
Set rngSrc = .Range(.Cells(2, 1), .Cells(lngSrcLastRow, 9))
'second change here**
rngSrc.Copy
rngDst.PasteSpecial Paste:=xlPasteValues
End With
lngDstLastRow = LastOccupiedRowNum(wksDst)
Set rngDst = wksDst.Cells(lngDstLastRow + 1, 1)
End If
Next wksSrc
End Sub
Public Function LastOccupiedRowNum(Sheet As Worksheet) As Long
Dim lng As Long
If Application.WorksheetFunction.CountA(Sheet.Cells) <> 0 Then
With Sheet
lng = .Cells.Find(What:="*", _
After:=.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
End With
Else
lng = 1
End If
LastOccupiedRowNum = lng
End Function

Excel vba if value is in column then [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I want to make a macro via an if then else function (maybe make use of a loop).
I have two separate files, named "orderregistratie" + "werkorder template".
I want to search in column A of sheets("datablad") in orderregistratie for the value sheets("export datablad").Range("A2") that is in werkorder template.
If this value exists in column A then copy the row of A2 from export datablad and paste it in the row where the value is found.
If it doesn't already exist I want to insert a new row at A2 in orderregistratie and copy the row of A2 from export datablad in the new row.
My VBA knowledge is not really good and I can't write the macro by myself. Is there anyone who can help me write it?
Give this a try. I'll adjust as needed. Just be double check if both workbooks are saved to your desktop.
Option Explicit
Private wkbOrderReg As Workbook, _
wkbOrderWork As Workbook, _
wkb As Workbook
Private wsOBJ As Worksheet, _
ws As Worksheet
Private rngSearch As Range, _
rngRow As Range, _
rng As Range, _
r As Range
Private strSearch As String
Public Sub DarudeSandStorm()
Dim LastRow As Long, _
LastColumn As Long
Dim arr As Variant
With Application.Workbooks
Set wkbOrderReg = .Open(Filename:=strVar("orderregistratie.xlsx"))
Set wkbOrderWork = .Open(Filename:=strVar("werkorder template.xlsx"))
End With
With wkbOrderWork
For Each ws In .Worksheets
Set wsOBJ = ws
If UCase$(wsOBJ.Name) = UCase$("export datablad") Then
With wsOBJ
Set rng = .Range(.Cells(2, 1), .Cells(2, 1))
strSearch = rng.Value
LastColumn = getLAST_COLUMN(wsOBJ)
Set rngRow = .Range(.Cells(2, 1), .Cells(2, LastColumn))
End With
arr = rngRow
Exit For
End If
Next ws
End With
With wkbOrderReg
For Each ws In .Worksheets
Set wsOBJ = ws
If UCase$(wsOBJ.Name) = UCase$("export datablad") Then
With wsOBJ
LastRow = getLAST_ROW(wsOBJ)
Set rngSearch = .Range(.Cells(1, 1), .Cells(LastRow, 1))
End With
For Each r In rngSearch
If UCase$(r.Value) = UCase$(strSearch) Then
r = arr
End If
Next r
End If
Next ws
End With
With Application
For Each wkb In .Workbooks
If Not wkb = .ThisWorkbook Then
With .Workbooks(wkb.Name)
.Save
.Close
End With
End If
Next wkb
End With
End Sub
Private Function getLAST_COLUMN(objWS As Worksheet) As Long
Dim wsDES As Worksheet, _
wkbSUB As Workbook, _
rngCHECK As Range
Set rngCHECK = objWS.Cells.Find(What:="*", _
After:=Range("A1"), _
LookIn:=xlFormulas, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False)
If Not rngCHECK Is Nothing Then
getLAST_COLUMN = objWS.Cells.Find("*", _
Range("A1"), _
xlFormulas, _
, _
xlByColumns, _
xlPrevious).Column
Else
getLAST_COLUMN = 1
End If
End Function
Private Function getLAST_ROW(objWS As Worksheet) As Long
Dim wsDES As Worksheet, _
wkbSUB As Workbook, _
rngCHECK As Range
Set rngCHECK = objWS.Cells.Find(What:="*", _
After:=Range("A1"), _
LookIn:=xlFormulas, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False)
If Not rngCHECK Is Nothing Then
getLAST_ROW = objWS.Cells.Find("*", _
Range("A1"), _
xlFormulas, _
, _
xlByRows, _
xlPrevious).Row
Else
getLAST_ROW = 1
End If
End Function
Private Function strVar(ByRef str As String) As String
strVar = Environ("Userprofile") & "\Desktop\" & str
End Function
#Mischa Urlings for this example i have save both workbooks ("orderregistratie" + "werkorder template") on my desktop so you must change their path on the code.
Option Explicit
Sub test()
Dim WbO As Workbook
Dim WbW As Workbook
Dim i As Long
Dim LRA As Long
Dim RowToCopy As Long
Dim Rowstr As Long
Dim Searchstr As String
Dim Address As Range
Dim Searchrng As Range
Workbooks.Open Filename:="C:\Users\xxxx\Desktop\" & "orderregistratie.xlsx" '<= Open Workbooks (for this example files are stored on desktop
Workbooks.Open Filename:="C:\Users\xxxx\Desktop\" & "werkorder template.xlsx"
Set WbO = Workbooks("orderregistratie.xlsx") '<= Set workbook to variables
Set WbW = Workbooks("werkorder template.xlsx")
LRA = WbW.Worksheets("export datablad").Range("A" & Rows.Count).End(xlUp).Row '<= Find Lastrow
For i = 2 To LRA '<= Loop column A (Workbook:werkorder template)
Searchstr = WbW.Worksheets("export datablad").Range("A" & i).Value '<= Set what to search for
Rowstr = i '<= Searchstr row
Set Searchrng = WbO.Worksheets("datablad").Columns("A") '<= Set where to search for
Set Address = Searchrng.Find(What:=Searchstr, LookAt:=xlWhole) '<= Result of the search
If Address Is Nothing Then
'If what we search for not found
WbO.Worksheets("datablad").Rows("2").Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
WbW.Worksheets("export datablad").Rows(Rowstr).EntireRow.Copy
WbO.Worksheets("datablad").Rows(2).PasteSpecial Paste:=xlPasteValues
Else
'If what we search for found
RowToCopy = Address.Row '<= Where we find the Searchstr
WbW.Worksheets("export datablad").Rows(i).EntireRow.Copy
WbO.Worksheets("datablad").Rows(RowToCopy).PasteSpecial Paste:=xlPasteValues
End If
Next i
With WbO
.Save
.Close '<= Close open workbooks
End with
With WbW
.Save
.Close '<= Close open workbooks
End with
End Sub

Moving Data with vba

I received data in column F,G,H, and I. I need to get that all into column E and take out the duplicates and the blank cells. The code i have so far works but it puts them all in the same row and doesn't keep them on their appropriate lines. I need them to stay on the same line they are currently in but to just transcribe over into the other column. This is what I have so far:
Sub Sample()
Dim ws As Worksheet
Dim LastRow As Long, lastCol As Long, i As Long
Dim Rng As Range, aCell As Range, delRange As Range '<~~ Added This
Dim MyCol As New Collection
~~> Change this to the relevant sheet name
Set ws = Sheets("Sheet1")
With ws
'~~> Get all the blank cells
Set delRange = .Cells.SpecialCells(xlCellTypeBlanks) '<~~ Added This
'~~> Delete the blank cells
If Not delRange Is Nothing Then delRange.Delete '<~~ Added This
LastRow = .Cells.Find(What:="*", After:=.Range("A1"), _
Lookat:=xlPart, LookIn:=xlFormulas, SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, MatchCase:=False).Row
lastCol = .Cells.Find(What:="*", After:=.Range("A1"), _
Lookat:=xlPart, LookIn:=xlFormulas, SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, MatchCase:=False).Column
Set Rng = .Range("A1:" & Split(.Cells(, lastCol).Address, "$")(1) & LastRow)
'Debug.Print Rng.Address
For Each aCell In Rng
If Not Len(Trim(aCell.Value)) = 0 Then
On Error Resume Next
MyCol.Add aCell.Value, """" & aCell.Value & """"
On Error GoTo 0
End If
Next
.Cells.ClearContents
For i = 1 To MyCol.Count
.Range("A" & i).Value = MyCol.Item(i)
Next i
'~~> OPTIONAL (In Case you want to sort the data)
.Columns(1).Sort Key1:=.Range("A1"), Order1:=xlAscending, Header:=xlGuess, _
OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom, _
DataOption1:=xlSortNormal
End With
End Sub
Try this.
Sub CopyThingy()
Dim wb As Workbook
Dim ws As Worksheet
Dim lCount As Long
Dim lCountMax As Long
Dim lECol As Long
Dim lsourceCol As Long
lECol = 5 '* E column
Set wb = ThisWorkbook
Set ws = wb.Sheets(1) '*Your Sheet
lCountMax = ws.Cells(ws.Rows.Count, "F").End(xlUp).Row
lsourceCol = 6
lCount = lCountMax
Do While lCount > 1
If ws.Cells(lCount, lsourceCol) <> "" Then
ws.Cells(lCount, lECol).Value = ws.Cells(lCount, lsourceCol).Value
End If
lCount = lCount - 1
Loop
lCountMax = ws.Cells(ws.Rows.Count, "G").End(xlUp).Row
lsourceCol = 7
lCount = lCountMax
Do While lCount > 1
If ws.Cells(lCount, lsourceCol) <> "" Then
ws.Cells(lCount, lECol).Value = ws.Cells(lCount, lsourceCol).Value
End If
lCount = lCount - 1
Loop
lCountMax = ws.Cells(ws.Rows.Count, "H").End(xlUp).Row
lsourceCol = 8
lCount = lCountMax
Do While lCount > 1
If ws.Cells(lCount, lsourceCol) <> "" Then
ws.Cells(lCount, lECol).Value = ws.Cells(lCount, lsourceCol).Value
End If
lCount = lCount - 1
Loop
End Sub

Resources