I am trying to delete a row if the value I check is 0.
So far I did almost the exact same in another set of workbooks, and it went just fine.
Both cases involve getting the agency's name from the startup workbook, then opening the first workbook of the set that needs deletion, looping through it and deleting what needs to be deleted, closing it and moving on to the next one (here I go from 2 to 2 because there's no need to go through all of them just yet)
I did my homework and looked it up beforehand. No, not my table nor my sheet nor my workbook nor any range is protected. Yes, I made sure to activate the workbook I want to affect, and it has only one sheet in it.
Using .Select works, deleting manually isn't possible. It seems a cell is locked, but even unlocking it doesn't allow me to manually delete the row.
here it's unlocked.
Edit - I tried running it with the original set of workbooks, and it worked just fine (the one I'm working with is a copy of the original)
Sub PetitTas()
deb = Now()
For i = 2 To 2
Workbooks("dimensionnement technos 2").Activate
Agence = Cells(i, 24)
Workbooks.Open "C:\Users\QNS691\Documents\Excel\par agence 2\" & Agence & ".xlsx"
Workbooks(Agence).Activate
For j = 2 To Cells(Rows.Count, 1).End(xlUp).Row
If Cells(j, 14) = 0 Then
Rows(j).EntireRow.Delete
End If
Next j
Workbooks(Agence).Close SaveChanges:=True
Next i
MsgBox deb & " " & Now()
End Sub
I am running out of ideas, please help!
Delete Entire Rows (Union)
Sub PetitTas()
Const FolderPath As String = "C:\Users\QNS691\Documents\Excel\par agence 2\"
Dim swb As Workbook: Set swb = ThisWorkbook ' workbook containing this code
Dim sws As Worksheet: Set sws = swb.Worksheets("Feuil1")
Dim sfCell As Range: Set sfCell = sws.Range("X2")
Dim slCell As Range: Set slCell = sfCell.Resize( _
sws.Rows.Count - sfCell.Row + 1).Find("*", , xlFormulas, , , xlPrevious)
Dim srg As Range: Set srg = sws.Range(sfCell, slCell)
Application.ScreenUpdating = False
Dim sCell As Range
Dim Agency As String
Dim FilePath As String
Dim dwb As Workbook
Dim dws As Worksheet
Dim durg As Range
Dim drg As Range
Dim dCell As Range
For Each sCell In srg.Cells
Agency = CStr(sCell.Value)
If Len(Agency) > 0 Then
FilePath = FolderPath & Agency & ".xlsx"
If Len(Dir(FilePath)) > 0 Then ' check if the file exists...
Set dwb = Workbooks.Open(FilePath) ' ... only then open it
Set dws = dwb.Worksheets(1) ' the one and only
Set drg = dws.Range("N2", dws.Cells( _
dws.Cells(dws.Rows.Count, "A").End(xlUp).Row, "N"))
For Each dCell In drg.Cells
If IsNumeric(dCell) Then
If dCell.Value = 0 Then
If durg Is Nothing Then
Set durg = dCell
Else
Set durg = Union(durg, dCell)
End If
End If
End If
Next dCell
If durg Is Nothing Then
dwb.Close SaveChanges:=False
Else
durg.EntireRow.Delete
Set durg = Nothing
dwb.Close SaveChanges:=True
End If
End If
End If
Next sCell
Application.ScreenUpdating = True
MsgBox "'PetitTas' is done.", vbInformation
End Sub
Overall you shouldn't be relying on the active sheet or the .Activate method. You should look at how-to-avoid-using-select-in-excel-vba
With that, explicitly use the Workbook and Worksheet when working with any Range or Cell.
Now your deletion is removing rows that your loop is depending on, so one fix is to loop backwards.
Below is my quick fixes to your code, but note it isn't tested.
Option Explicit
Public Sub PetitTas()
Dim deb As Date ' Was missing
deb = Now()
Dim i As Long ' Was missing
For i = 2 To 2
' Use the specific worksheet reference.
' Using activate isn't reliable and
' hurts performance
Dim agence As Variant
agence = Workbooks("dimensionnement technos 2") _
.Worksheets(1) _
.Cells(i, 24)
' Capture your workbook into a variable for the
' same reason above, activate is not your friend
' in most cases. Only time is when you need to display
' a user a specific sheet.
Dim wb As Workbook
Set wb = Workbooks.Open( _
"C:\Users\QNS691\Documents\Excel\par agence 2\" & _
agence & ".xlsx" _
)
' Use a with statement to capture your
' worksheet, that way `.Cells` is pointing
' explicitly to the correct sheet.
With wb.Worksheets(1)
Dim j As Long ' Was missing
' When deleting in a loop, either capture
' all ranges into a variable a delete after loop
' or step backwards. I steped backwards for this demo
' for simplicity, but single deletion is more performant
For j = .Cells(.Rows.Count, 1).End(xlUp).Row To 2 Step -1
If .Cells(j, 14) = 0 Then
.Rows(j).EntireRow.Delete
End If
Next j
End With
wb.Close SaveChanges:=True
Next i
MsgBox deb & " " & Now()
End Sub
Related
I am trying to skip all of the sheets that are"xlSheetHidden" or "xlSheetVeryHidden". I have recently started using VBA to help speed up processes at my work when python wasn't allowing for what was needed. I currently have the following code:
Sub Merge_Sheets()
Dim Work_Sheets() As String
ReDim Work_Sheets(Sheets.Count)
For i = 0 To Sheets.Count - 1
Work_Sheets(i) = Sheets(i + 1).Name
Next i
Sheets.Add.Name = "Combined Sheet"
Dim Column_Index As Integer
Column_Index = Worksheets(1).UsedRange.Cells(1, 1).Column
Dim Row_Index As Integer
Row_Index = 0
For i = 0 To Sheets.Count - 2
Set Rng = Worksheets(Work_Sheets(i)).UsedRange
Rng.Copy
Worksheets("Combined Sheet").Cells(Row_Index + 1, Column_Index).PasteSpecial Paste:=xlPasteValues
Row_Index = Row_Index + Rng.Rows.Count + 1
Next i
Application.CutCopyMode = False
End Sub
I have tried inserting If .Visible = xlSheetVisible Then but cannot get it to work.
I have also tried to make it work with:
For Each Sheets In ActiveWorkbook.Worksheets
If Sheet.Visible = xlSheetVisible Then
However this still doesn't seem to work, any help would be greatly appreciated.
You did not use the for each correctly. In your code you loop over sheets with the name Sheets, then in the loop you refer to Sheet
For Each Sheets In ActiveWorkbook.Worksheets
If Sheet.Visible = xlSheetVisible Then '// Doesn't work!
So you probaby only needed to fix up this variable naming:
For Each ws In ActiveWorkbook.Worksheets
If ws.Visible = xlSheetVisible Then
Or
For Each sht In ActiveWorkbook.Worksheets
If sht.Visible = xlSheetVisible Then
sht and ws are traditional vba coding variable names for sheet/worksheet objects. But you can use any name you like. However, not Sheets as a variable name, as that is already the name of the built-in Sheets collection.
Merge (Append) Visible Worksheets
Option Explicit
Sub MergeWorksheets()
' Define constants.
Const dName As String = "Combined Sheet"
Const dFirstCellAddress As String = "A1"
' Reference the workbook ('wb').
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Application.ScreenUpdating = False
' Delete the destination worksheet ('dws') if it exists.
Dim dws As Worksheet
On Error Resume Next
Set dws = wb.Worksheets(dName)
On Error GoTo 0
If Not dws Is Nothing Then
Application.DisplayAlerts = False
dws.Delete
Application.DisplayAlerts = True
End If
' Write the number of worksheets to a variable ('swsCount').
Dim swsCount As Long: swsCount = wb.Worksheets.Count
' Add the names of all the visible worksheets
' to an array ('WorksheetNames').
' A better choice here is to use a collection or a dictionary
' where it is not important to know the number of elements (items).
' But no harm done.
Dim WorksheetNames() As String: ReDim WorksheetNames(1 To swsCount)
Dim sws As Worksheet ' Current Source Worksheet
Dim n As Long ' Visible Worksheets Count(er)
For Each sws In wb.Worksheets
If sws.Visible = xlSheetVisible Then
n = n + 1
WorksheetNames(n) = sws.Name
End If
Next sws
If n = 0 Then
MsgBox "No visible worksheets found.", vbExclamation
Exit Sub
End If
' Resize the array to the actual number of found visible worksheets
' (not necessary since later we're looping with 'For n = 1 to n').
If n < swsCount Then ReDim Preserve WorksheetNames(1 To n)
' Add and reference a new worksheet, the destination worksheet ('dws').
' First sheet...
Set dws = wb.Worksheets.Add(Before:=wb.Sheets(1))
' ... or e.g. last sheet
'Set dws = wb.Worksheets.Add(After:=wb.Sheets(wb.Sheets.Count))
dws.Name = dName ' rename
' Reference the first cell of the destination range ('dfCell').
Dim dfCell As Range: Set dfCell = dws.Range(dFirstCellAddress)
Dim srg As Range ' Current Source Range
Dim drg As Range ' Current Destination Range
For n = 1 To n
' Reference the source worksheet.
Set sws = wb.Worksheets(WorksheetNames(n))
' Reference the used range in the source worksheet.
Set srg = sws.UsedRange
' Reference the destination range, the destination cell
' resized by the number of rows and columns of the source range.
Set drg = dfCell.Resize(srg.Rows.Count, srg.Columns.Count)
' Write the values from the source range to the destination range.
drg.Value = srg.Value
' Reference the next destination first cell.
Set dfCell = dfCell.Offset(srg.Rows.Count)
Next n
Application.ScreenUpdating = True
' Inform to not wonder if the code has run or not.
MsgBox "Worksheets merged.", vbInformation
End Sub
I've got a spreadsheet with data from column A:AA. I'm trying to copy over all of the data from sheet CycleCountResearch in "workbook-a" to CycleCountResearch sheet in "workbook-b". All of the data except for column AA copy's over. Column AA contains the filename, so that when it is copied over from workbook a to workbook b, the user can look at the data in workbook b and know which file the data came from. Is there any recommendation on how to fix column AA not copying over?
Here is the code so far:
Sub Export()
Dim FileName As String
FileName = "\\InventoryControlDatabase\DoNotOpen\DoNotOpenDCAtest.xlsx"
'Call function to check if the file is open
If IsFileOpen(FileName) = False Then
Application.ScreenUpdating = False
Worksheets("CycleCountResearch").Unprotect "123"
Dim LR As Long
Dim src As Workbook
LR = Worksheets("CycleCountResearch").Cells(Rows.Count, "B").End(xlUp).Row
Set src = Workbooks.Open("\\InventoryControlDatabase\DoNotOpen\DoNotOpenDCAtest.xlsx")
ThisWorkbook.Worksheets("CycleCountResearch").AutoFilterMode = False
ThisWorkbook.Worksheets("CycleCountResearch").Range("A4:AA" & LR).AutoFilter Field:=23, Criteria1:="Done", _
Operator:=xlFilterValues
On Error Resume Next
ThisWorkbook.Worksheets("CycleCountResearch").Range("A5:AA" & LR).SpecialCells(xlCellTypeVisible).Copy
src.Activate
src.Worksheets("CycleCountResearch").Range("A" & Rows.Count).End(xlUp).Offset(1, 0).PasteSpecial xlPasteValues
'src.Worksheets("CycleCountCompleted").UsedRange.RemoveDuplicates Columns:=1, Header:=xlYes
Workbooks("DoNotOpenDCA.xlsx").Close SaveChanges:=True
Application.ScreenUpdating = True
Call UpdateMasterLog
Call ClearUpdates
ThisWorkbook.Worksheets("CycleCountResearch").Range("K2:K2").ClearContents
'Clears the name of the user editing the sheet
Else
MsgBox "Someone else is saving. Please wait a moment and try again"
Exit Sub
End If
End Sub
Backup Data
This is how I see it. Read through it before running it because you may have to rearrange some lines in the Finishing Touches part (e.g. ClearUpdates, UpdateMasterLogs).
The best advice from it should be about using variables. They will not slow down the code but will make it more readable, the obvious example being the variables srg, sdrg, and sdfrg.
Option Explicit
Sub ExportData()
Const dFilePath As String _
= "\\InventoryControlDatabase\DoNotOpen\DoNotOpenDCAtest.xlsx"
'Call function to check if the file is open
If Not IsFileOpen(dFilePath) Then ' source workbook is closed
Application.ScreenUpdating = False
' Source
Dim swb As Workbook: Set swb = ThisWorkbook
Dim sws As Worksheet: Set sws = swb.Worksheets("CycleCountResearch")
sws.Unprotect "123"
sws.AutoFilterMode = False
Dim slRow As Long: slRow = sws.Range("B" & sws.Rows.Count).End(xlUp).Row
' Source Range (has headers)
Dim srg As Range: Set srg = sws.Range("A4:AA" & slRow)
srg.AutoFilter Field:=23, Criteria1:="Done" ' '23' is 'W'
' Source Data Range (no headers)
Dim sdrg As Range: Set sdrg = srg.Resize(srg.Rows.Count - 1).Offset(1)
' Source Data Filtered Range
Dim sdfrg As Range
On Error Resume Next ' prevent error if no cells
Set sdfrg = sdrg.SpecialCells(xlCellTypeVisible)
On Error GoTo 0
If Not sdfrg Is Nothing Then
' Destination
Dim dwb As Workbook: Set dwb = Workbooks.Open(dFilePath)
Dim dws As Worksheet: Set dws = dwb.Worksheets("CycleCountResearch")
Dim dCell As Range
Set dCell = dws.Range("A" & dws.Rows.Count).End(xlUp).Offset(1)
sdfrg.Copy¸
dCell.PasteSpecial Paste:=xlPasteValues
'dwb.Worksheets("CycleCountCompleted").UsedRange.RemoveDuplicates _
Columns:=1, Header:=xlYes
dwb.Close SaveChanges:=True
' Finishing Touches
UpdateMasterLog
ClearUpdates
'Clear the name of the user editing the sheet
sws.Range("K2:K2").ClearContents
sws.AutoFilterMode = False
sws.Protect "123"
Application.ScreenUpdating = True '
MsgBox "Data exported.", vbInformation
Else ' no filtered data
sws.AutoFilterMode = False
MsgBox "No filtered data.", vbCritical
'Exit Sub
End If
Else ' source workbook is open
MsgBox "Someone else is saving. Please, try again later.", vbExclamation
'Exit Sub
End If
End Sub
So, I have one excel workbook containing around 80 sheets, the sheets are named as Input, Input(1), input, INPUT, INPUT(2) and Output, Output(1), Output(2), output, OUTPUT and so on, you get the idea... I want to create a macro which creates two mastersheets in the Workbook named "MASTERSHEET INPUT" and "MASTERSHEET Output". The macro should copy all the data from any sheet having any variation of input in its sheet name and paste it one into the MASTERSHEET INPUT and the same goes for the sheets named output which will be pasted into MASTERSHEET OUTPUT. I'm relatively new to VBA and I'd really appreciate it if someone could help me out.
Thanks in advance!
This is the code I was using previously
Sub CombineData()
Dim I As Long
Dim xRg As Range
On Error Resume Next
Worksheets.Add Sheets(1)
ActiveSheet.Name = "MasterSheet"
For I = 2 To Sheets.Count
Set xRg = Sheets(1).UsedRange
If I > 2 Then
Set xRg = Sheets(1).Cells(xRg.Rows.Count + 1, 1)
End If
Sheets(I).Activate
ActiveSheet.UsedRange.Copy xRg
Next
End Sub
But this merges all the sheets in the workbook into one without checking the sheet name.
I tried using this one next but this just pastes the first Output sheet into both mastersheets and then ends:
Sub CombineData()
Dim I As Long
Dim xRg As Range
Dim xWs As Worksheet
Application.ScreenUpdating = False
Application.DisplayAlerts = False
On Error Resume Next
Worksheets.Add Sheets(1)
ActiveSheet.Name = "MasterSheet Output"
For I = 2 To Sheets.Count
Set xRg = Sheets(1).UsedRange
If I > 2 Then
Set xRg = Sheets(1).Cells(xRg.Rows.Count + 1, 1)
End If
For Each xWs In Application.ActiveWorkbook.Worksheets
If xWs.Name = "OUTPUT*" Or xWs.Name = "output*" Or xWs.Name = "Output*" Then
Sheets(I).Activate
ActiveSheet.UsedRange.Copy xRg
End If
Next
Next
On Error Resume Next
Worksheets.Add Sheets(1)
ActiveSheet.Name = "MasterSheet Input"
For I = 3 To Sheets.Count
Set xRg = Sheets(1).UsedRange
If I > 2 Then
Set xRg = Sheets(1).Cells(xRg.Rows.Count + 1, 1)
End If
For Each xWs In Application.ActiveWorkbook.Worksheets
If xWs.Name = "INPUT*" Or xWs.Name = "input*" Or xWs.Name = "Input*" Then
Sheets(I).Activate
ActiveSheet.UsedRange.Copy xRg
End If
Next
Next
Application.DisplayAlerts = True
Application.ScreenUpdating = True
Call DeleteAllSheetsExceptMaster
End Sub
I also tried using this but this does absolutely nothing:
Sub CombineData()
Dim I As Long
Dim xrg As Range
Dim counter As Long
Dim xWs1 As Worksheet
Dim xWs2 As Worksheet
Application.ScreenUpdating = False
Application.DisplayAlerts = False
On Error Resume Next
For counter = 1 To 2
Worksheets.Add Sheets(1)
If counter = 1 Then
ActiveSheet.Name = "MasterSheet Input"
Set xWs1 = ActiveSheet
End If
If counter = 2 Then
ActiveSheet.Name = "MasterSheet Output"
Set xWs2 = ActiveSheet
End If
Next counter
For I = 2 To Sheets.count
Set xrg = Sheets(1).UsedRange
If I > 2 Then
Set xrg = Sheets(1).Cells(xrg.Rows.count + 1, 1)
End If
Sheets(I).Activate
If Sheets(I).Name = "OUTPUT*" Or Sheets(I).Name = "output*" Or Sheets(I).Name = "Output*" Then
ActiveSheet.UsedRange.Copy xWs2
End If
If Sheets(I).Name = "INPUT*" Or Sheets(I).Name = "input*" Or Sheets(I).Name = "Input*" Then
ActiveSheet.UsedRange.Copy xWs1
End If
Next
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
Create Master Sheets
The following will delete each of the master worksheets if they exist and then create new ones. Then it will copy the data from the current region starting in A1 of the defined source worksheets to the appropriate master worksheets (read OP's requirements).
The Code
Option Explicit
Sub createMasterSheets()
' Define constants incl. the Names Arrays and the workbook.
Const srcFirst As String = "A1"
Const tgtFirst As String = "A1"
Dim srcNames As Variant
srcNames = Array("iNpUt", "oUtPuT") ' Case does not matter.
Dim tgtNames As Variant
tgtNames = Array("MasterIn", "MasterOut")
Dim wb As Workbook
Set wb = ThisWorkbook
' Define lower and upper subscripts of the 1D arrays:
' srcNames, tgtNames, Dicts
Dim sFirst As Long
sFirst = LBound(srcNames)
Dim sLast As Long
sLast = UBound(srcNames)
' Turn off screen updating.
Application.ScreenUpdating = False
' Add Target Worksheets.
Dim ws As Worksheet
Dim n As Long
For n = sLast To sFirst Step -1
On Error Resume Next
Set ws = wb.Sheets(tgtNames(n))
On Error GoTo 0
If Not ws Is Nothing Then
Application.DisplayAlerts = False
wb.Sheets(tgtNames(n)).Delete
Application.DisplayAlerts = True
End If
wb.Worksheets.Add Before:=wb.Sheets(1)
ActiveSheet.Name = tgtNames(n)
Next n
' Define Dictionaries Array and populate it with Dictionaries.
' The Dictionaries will hold the Data Arrays.
Dim Dicts As Variant
ReDim Dicts(sFirst To sLast)
Dim dict As Object
For n = sFirst To sLast
Set dict = CreateObject("Scripting.Dictionary")
Set Dicts(n) = dict
Next n
' Declare variables.
Dim wsName As String ' Current Worksheet Name
Dim rng As Range ' Current Source Range, Current Target Cell Range
Dim m As Long ' Subscript of Current Data Array in Current Dictionary
' of Dictionaries Array
' Write values from Source Ranges to Data Arrays.
For Each ws In wb.Worksheets
wsName = ws.Name
For n = sFirst To sLast
If InStr(1, wsName, srcNames(n), vbTextCompare) = 1 Then
' Define Source Range. You might need to do this in another way.
Set rng = ws.Range(srcFirst).CurrentRegion
m = m + 1
Dicts(n)(m) = rng.Value ' This will fail later if one cell only.
Exit For
End If
Next n
Next ws
' Declare variables
Dim Key As Variant ' Current Key in Current Dictionary
' of Dictionaries Array.
' Write values from Data Arrays to Target Ranges.
For n = sFirst To sLast
Set rng = wb.Worksheets(tgtNames(n)).Range(tgtFirst)
Set ws = wb.Worksheets(tgtNames(n))
For Each Key In Dicts(n).Keys
rng.Resize(UBound(Dicts(n)(Key), 1), _
UBound(Dicts(n)(Key), 2)).Value = Dicts(n)(Key)
Set rng = rng.Offset(UBound(Dicts(n)(Key), 1))
Next Key
Next n
' Turn on screen updating.
Application.ScreenUpdating = True
' Inform user.
MsgBox "Sheets created, data transferred.", vbInformation, "Success"
End Sub
See if this works for you.
Edit: fixed case sensitivity.
Sub CopyFromWorksheets()
Dim wrk As Workbook 'Workbook object - Always good to work with object variables
Dim sht As Worksheet 'Object for handling worksheets in loop
Dim trg As Worksheet 'Input Master
Dim trg2 As Worksheet 'Output Master
Dim rng As Range 'Range object
Set wrk = ActiveWorkbook 'Working in active workbook
'Add new worksheet as the last worksheet
Set trg = wrk.Worksheets.Add(After:=wrk.Worksheets(wrk.Worksheets.Count))
'Rename the new worksheet
trg.Name = "Input Master"
'Add new worksheet as the last worksheet
Set trg2 = wrk.Worksheets.Add(After:=wrk.Worksheets(wrk.Worksheets.Count))
'Rename the new worksheet
trg2.Name = "Output Master"
'We can start loop
For Each sht In wrk.Worksheets
'If worksheet in loop is the last one, stop execution (it is Master worksheet)
If sht.Index = wrk.Worksheets.Count - 1 Then
Exit For
ElseIf LCase(sht.Name) Like "*" & "input" & "*" Then
Set rng = sht.Range(sht.Cells(1, 1), sht.Cells(65536, 1).End(xlUp))
'Put data into the Master worksheet
trg.Cells(65536, 1).End(xlUp).Offset(1).Resize(rng.Rows.Count, rng.Columns.Count).Value = rng.Value
ElseIf LCase(sht.Name) Like "*" & "output" & "*" Then
Set rng = sht.Range(sht.Cells(1, 1), sht.Cells(65536, 1).End(xlUp))
'Put data into the Master worksheet
trg2.Cells(65536, 1).End(xlUp).Offset(1).Resize(rng.Rows.Count, rng.Columns.Count).Value = rng.Value
End If
Next sht
'Fit the columns in Master worksheet
trg.Columns.AutoFit
trg.Rows(1).Delete
trg.Columns.AutoFit
trg2.Rows(1).Delete
End Sub
I have some tables from Excel that will be updated every month or so, what I am trying to do is to copy and paste those ranges from a "master workbook" to some several sheets. The way this works is I have 20 plus workbooks with those ranges "tables" already there, but I am having to manually open those workbooks then copy and paste the new values from the master workbook and close it.
Sub openwb()
Dim wkbk As Workbook
Dim NewFile As Variant
Dim ws As Worksheet
Dim rngCopy As Range, aCell As Range, bcell As Range
Dim strSearch As String
Dim StrFile As Variant
Dim wb2 As Excel.Workbook
Application.DisplayAlerts = True
Application.ScreenUpdating = True
StrFile = Dir("C:\temp\*.xlsx*")
Do While Len(StrFile) > 0
Set wb = Workbooks.Open(StrFile)
'NewFile = Application.GetOpenFilename("microsoft excel files (*.xl*), *.xl*")
'
'If NewFile <> False Then
'Set wkbk = Workbooks.Open(NewFile)
'''**********************
strSearch = "Descitption"
Set ws = Worksheets("TestCases")
With ws
Set aCell = .Columns(4).Find(What:=strSearch, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not aCell Is Nothing Then
Set bcell = aCell
If rngCopy Is Nothing Then
Set rngCopy = .Rows((aCell.Row + 1) & ":" & (aCell.Row + 2))
Else
Set rngCopy = Union(rngCopy, .Rows((aCell.Row + 1) & ":" & (aCell.Row + 2)))
End If
Do
Set aCell = .Columns(4).FindNext(After:=aCell)
If Not aCell Is Nothing Then
If aCell.Address = bcell.Address Then Exit Do
If rngCopy Is Nothing Then
Set rngCopy = .Rows((aCell.Row + 1) & ":" & (aCell.Row + 2))
Else
Set rngCopy = Union(rngCopy, .Rows((aCell.Row + 1) & ":" & (aCell.Row + 2)))
End If
Else
Exit Do
End If
Loop
Else
MsgBox SearchString & " not Found"
End If
'~~> I am pasting to Output sheet. Change as applicable
Set wb2 = Workbooks.Open("C:\temp\Bulk tool\test1.xlsm")
If Not rngCopy Is Nothing Then rngCopy.Copy 'paste to another worksheet Sheets("Output").Rows(1)
End With
'**************************
ActiveWorkbook.Close SaveChanges:=False
Application.DisplayAlerts = True
Application.ScreenUpdating = True
StrFile = Dir
Loop
End Sub
The range is dynamic, it can change from 2 rows to 20, but to give an example A1:K20 and it will go to the same range to another workbook.
first off let me thank everyone helping me on this.
here is what I have so far (see code)
when I run it I am getting error 1004 not sure what I changed but it was working fine, also what I am trying to do, is to copy to another worksheet.
Copying and pasting values in a worksheet uses the Range.Copy and Range.PasteSpecial.
An example code is as follows:
Sub CopyThis()
Dim Sht1 As Worksheet, Sht2 As Worksheet
Set Sht1 = ThisWorkbook.Sheets(1)
Set Sht2 = ThisWorkbook.Sheets(2)
Sht1.Range("A1:D4").Copy
Sht2.Range("A1:D4").PasteSpecial xlPasteAll
End Sub
Alternatively, you can also loop through values. I usually do this out of preference because I often do "If Then" in loops
Sub CopyThis2()
Dim Sht1 As Worksheet, Sht2 As Worksheet
Set Sht1 = ThisWorkbook.Sheets(1)
Set Sht2 = ThisWorkbook.Sheets(2)
Dim i As Long, j As Long
For i = 1 To 4
For j = 1 To 4
Sht2.Cells(i, j).Value = Sht1.Cells(i, j).Value
Next j
Next i
End Sub
Perhaps you can do little tricks with coding to make it faster. Like in this Answer below
Looping through files in a Folder
You can Also use Application.Screenupdating = False before the loop & True after the loop, so that your process would be way faster. In the Loop you can put the Code suggested by Parker.R ....
Also, there is no other way to copy data from workbooks without opening them in VBA.All you can do it play with the way files are being opened and closed so that the process becomes faster.
Other than Screenupdating few more properties you can Set As per this Link
Code to loop Using FSO
Application.DisplayAlerts = False
Application.ScreenUpdating = False
Dim objFSO As Object
Dim objFolder, sfol As Object
Dim objFile As Object
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFSO.getFolder(f_add) ''''f_add is the Address of the folder
'''' Loop For Files in That Folder
For Each objFile In objFolder.Files
''''Your Code
Next
'''' Loop for All the Subfolders in The Folder
For Each sfol In objFolder.subfolders
''' Your Code Here
Next
Application.DisplayAlerts = True
Application.ScreenUpdating = True
i am attempting to write a script that goes over a specific column and then copies all rows containing the value of "rejected" in said column to a new excel file/workbook.
Everything seems to work just fine except for the actual Paste command which fails every time.
The code:
Sub button()
Dim x As String
Dim found As Boolean
strFileFullName = ThisWorkbook.FullName
strFileFullName = Replace(strFileFullName, ".xlsm", "")
strFileFullName = strFileFullName + "_rejected.xlsx"
' MsgBox strFileFullName
Set oExcel = CreateObject("Excel.Application")
Set obook = oExcel.Workbooks.Add(1)
Set oSheet = obook.Worksheets(1)
oSheet.Name = "Results"
' Select first line of data.
Range("E2").Select
' Set search variable value.
x = "rejected"
' Set Boolean variable "found" to false.
found = False
' Set Do loop to stop at empty cell.
Do Until IsEmpty(ActiveCell)
' Check active cell for search value.
If ActiveCell.Value = "" Then
Exit Do
End If
If ActiveCell.Value = x Then
found = True
rowToCopy = ActiveCell.Row
ActiveSheet.Rows(ActiveCell.Row).Select
Selection.Copy
oSheet.Range("A1").Select
lastrow = oSheet.Cells(Rows.Count, "B").End(xlUp).Row
' oSheet.Rows(1).Select.PasteSpcial
End If
' Step down 1 row from present location.
ActiveCell.Offset(1, 0).Select
Loop
' Check for found.
If found = True Then
MsgBox "Value found in cell " & ActiveCell.Address
Else
MsgBox "Value not found"
End If
obook.SaveAs strFileFullName
obook.Close
End Sub
Any idea why i keep failing with the paste function?
Thanks!
Try this, no selects involved.
Sub AddWB()
Dim nwBk As Workbook, WB As Workbook, Swb As String
Dim Rws As Long, Rng As Range, c As Range, sh As Worksheet
Set WB = ThisWorkbook
Set sh = WB.Worksheets("Sheet1")
Rws = sh.Cells(Rows.Count, "E").End(xlUp).Row
Set Rng = Range(sh.Cells(2, 5), sh.Cells(Rws, 5))
Set nwBk = Workbooks.Add(1)
Swb = WB.Path & "\" & Mid(WB.Name, 1, Len(WB.Name) - 5) & ".xlsx"
MsgBox Swb
For Each c In Rng.Cells
If c = "x" Then c.EntireRow.Copy nwBk.Sheets(1).Cells(Rows.Count, "A").End(xlUp).Offset(1, 0)
Next c
nwBk.SaveAs Filename:=Swb
End Sub
XLorate.com
Your PasteSpecial command might fail because it's spelled incorrectly. At any rate, if you've got a lot of rows, you should consider something faster than looping through them.
This uses AutoFilter to copy all rows meeting the criteria in one pass. It will also copy the header row. If that's not what you want, you can delete row 1 of the new worksheet after the copy:
Sub CopyStuff()
Dim SearchString As String
Dim Found As Boolean
Dim wsSource As Excel.Worksheet
Dim wbTarget As Excel.Workbook
Dim wsTarget As Excel.Worksheet
Dim LastRow As Long
Set wsSource = ActiveSheet
SearchString = "rejected"
With wsSource
Found = Application.WorksheetFunction.CountIf(.Range("E:E"), SearchString) > 0
If Not Found Then
MsgBox SearchString & " not found"
Exit Sub
End If
Set wbTarget = Workbooks.Add(1)
Set wsTarget = wbTarget.Worksheets(1)
wsTarget.Name = "Results"
.Range("E:E").AutoFilter
LastRow = .Range("E" & .Rows.Count).End(xlUp).Row
.Range("E:E").AutoFilter field:=1, Criteria1:=SearchString
.Range("E1:E" & LastRow).SpecialCells(xlCellTypeVisible).EntireRow.Copy _
Destination:=wsTarget.Range("A1")
End With
wbTarget.SaveAs Replace(ThisWorkbook.FullName, ".xlsm", "_rejected.xlsx")
wbTarget.Close
End Sub
I didn't use your code to create a new Excel instance, as I couldn't see why that would be needed here, and it could cause problems. (For example,yYou don't kill the instance in your original code.)