Copy/Paste For Loop - vba

I am working on a for loop that takes an entry on the first page of a worksheet, and copy and pastes it to the remaining sheets in the workbook, with the array size being Worksheets.Count. Specifically, I am having trouble finding a way to call on each table in each specific worksheet. I was trying to select the table based on the counter in the for loop such that:
For i=1 to Worksheets.count
Range.("Table(Counter").Select
Next i
but it doesn't work. Is there a better way to make sure that my code selects the proper table in each successive worksheet? I am still pretty new to VBA, so any and all help is appreciated!

If you are using the counter, I am assuming your tables are named Table1, Table2, and so on for each worksheet.
The problem here is that you need to make sure that the Worksheet Index is in the same sequence as your table.
You can try this alternative which is not dependent on the sequence of the worksheet and name of the Tables.
Dim sh As Worksheet
For Each sh In ThisWorkbook.Worksheets
sh.ListObjects(1).Range.Select
' to check if you got the correct object, add below line
Debug.Print sh.ListObjects(1).Range.Address(, , , True)
Next
Above is considering you only have one(1) Table in each Sheet.

Related

Excel 2013: Use macro to copy and subsequently add data from one sheet to another within same workbook

I have used the various methods pointed out in this forum and none seem to work, so I will try to be more specific.
I have a workbook called LIBRARY.xlsm.
This workbook contains two worksheets: CALCULATOR and CUTS.
The worksheet CALCULATOR contains two tables: INPUT and OUTPUT.
I enter data into INPUT, values are calculated and automatically entered into OUTPUT.
I create a button below OUTPUT with macro to copy data in OUTPUT to worksheet CUTS.
I enter new data into INPUT, which then updates OUTPUT.
Now I want to copy this new data to CUTS without overwriting or deleting previous data.
Since this project is divided into 5 sections, I should end up with five tables in the worksheet CUTS that I can then print out.
The INPUT table encompasses cells A1:M31, which does not matter (I’m not copying this).
The OUTPUT table occupies cells O6:S26. This is the data that needs to be copied.
Placement into worksheet CUTS can start at cell A1 (which means the table will have the range A1:E20). I would like to skip a column and then place the next data set. Thus, the next data set should begin at G1 (G1:K20), then at M1:Q20 and so forth). Maybe only go three tables across and then start next three below (separated by row).
Here is the code tried to use. Problem is, it does not retain the values and it overwrites the previous data.
Sub Create_CUTS ()
Dim sourceSheet As Worksheet
Dim sourceRange As Range
Dim sourceRows As Integer
Set sourceSheet = Worksheets("CALCULATOR")
sourceRows = WorksheetFunction.CountA(sourceSheet.Range("A:A"))
Set sourceRange = sourceSheet.Range("O6:S26" & sourceRows)
Dim targetSheet As Worksheet
Dim targetRange As Range
Dim targetRows As Integer
Set targetSheet = Worksheets("CUTS")
targetRows = WorksheetFunction.CountA(targetSheet.Range("A:A"))
Set targetRange = targetSheet.Range("A" & targetRows + 1 & ":A" & targetRows + 1 + sourceRows)
sourceRange.Copy Destination:=targetRange
End Sub
Thank you, everyone
-Grumps
There are a few ways to do this. The easiest is probably to just reference the usedrange of the target sheet to know where you left off with the last paste.
lastUsedRow = targetSheet.UsedRange.Rows.Count
lastColumnUsed = targetSheet.UsedRange.Columns.Count
Then you just add a column or row and paste the table in the new location. If the column count is 22 or greater, add a row and paste at "A" and the lastUsedRow + 2. There is some potential for this to be wrong if the sheets are saved with cells that are empty, but excel reads them as "used" (somehow people I work with manage to do this all the time, I don't even know how they do it). It sounds like this is something that users won't be manipulating, so I wouldn't think that would be a problem, but if it is a possible problem for you, you can use a loop to find the next empty cell instead of using the built in "usedrange" collection.

Referencing multi-sheet named range in VBA

I have a named range in Excel that I am trying to clear using VBA.
The problem with the range is that spans across multiple sheets and I am not sure how to properly reference the named range in VBA since it covers multiple sheets.
The Named Range "Counts" is set to Workbook scope with the following cell references:
=Sheet1!$A$1, Sheet2!$A$1, Sheet3!$A$1
When clearing a named range where it only has cells referenced on one sheet I use the following:
ThisWorkbook.Sheets("Sheet1").Range("Counts").ClearContents
I have tried the following but neither seemed to work.
ThisWorkbook.Range("Counts").ClearContents
and
Range("Counts").ClearContents
The last gives me a global error.
Instead of a range that goes across multiple sheets (which does not work, as we have established), you need a worksheet scoped range in each sheet.
When defining a range name you can set its scope to workbook or the current sheet. This way you can have the same range name in many sheets.
Use VBA to loop through all worksheet, access the ws.Range("TheRangeName") on the current sheet and clear its contents.
That's a cleaner approach.
I would write something that displays the names and you can use that to remove it...
In the immediate window:
For i = 1 to names.count:Debug.print i, Names(i).RefersTo, Names(i).name:next
You can then either use th name or the index to remove the particular name you want.
Hope that helps.
Rory Archibald states on his website post about named ranges that: A Range object can only refer to cells on one worksheet. You cannot refer to cells on different sheets with one Range object.
So I am unable to accomplish what I was wanting but I should be able to just create multiple named ranges and just clear them one at a time.
I was able to complete the code for this as follows with inspiration from teylyn
Public Sub ClearRanges()
'Checks if named Range exists on sheet if it does then clear contents
Dim ws As Worksheet
Application.DisplayAlerts = False
For Each ws In ThisWorkbook.Worksheets
If Len(ws.Range("Counts").Name) <> 0 Then
ws.Range("Counts").ClearContents
End If
Next ws
Application.DisplayAlerts = True
End Sub

VBA script to copy a column in the next sheet and paste to the next empty column in the first sheet

I’d need to write a short VBA script for the following situation. The workbook contains multiple sheets. The first sheet is the summary sheet. After the summary sheet there is an irregular number of sheets that contain the information I would like to display on the summary sheet. The information is always in “Column B”. The script should copy “Column B” of each sheet and paste it to the next empty column in the summary sheet. In other words, it should copy “Column B” in “Sheet 2” and paste it to the next empty column in “Sheet 1”, then copy “Column B” in “Sheet 3” and paste again to the next empty column in “Sheet 1”, etc. etc.
All the help is appreciated, thank you!
You will need to declare a Worksheet type variable (e.g. Dim ws As Worksheet), to loop by a For Each ws In Activeworkbook.Worksheets ... Next ws. Then you need to define which sheet is the master sheet. I recommend once again a Worksheet, e.g. Set wsMain = ActiveWorkbook.Worksheets("Summary").
To complete it use a
wsMain.Cells.Find("*",SearchOrder:=xlByColumns,SearchDirection:=xlPrevious).Column
to tell you the index of the last used column in your summary sheet. You can either store it in a variable then increase it by one in your loop or run it in your loop (not resource-efficient but who cares about that two milliseconds).
You can reference columns by index which in your case will be ws.Cells.Columns(2) and wsMain.Cells.Columns(LastColumn + 1).
Have fun writing your code, I hope I could help!
This worked:
Sub NextWsToNextEmptyColumn()
Dim ws As Worksheet
For Each ws In ActiveWorkbook.Worksheets
ws.Cells.Columns(2).Copy Sheets(1).Cells(1, Columns.Count).End(xlToLeft).Offset(, 1)
Next ws
End Sub

Excel VBA Delete empty rows in table

I have a table tabelaClientes in Sheet "Clientes" and I want to delete the rows where the field "Nome" is empty.
How do I do that?
This is what I'm trying:
Sub Cliente()
Dim ws As Worksheet
Dim row As Range
Set ws = Sheets("Clientes")
For Each row In ws.[tabelaClientes[Nome]].Rows
If row.Value = "" Then
row.Delete
End If
Next
Exit Sub
But this is deleting only some of the rows where Nome is empty, not all, why?
You can use a very simple call to SpecialCells() to do that instead of using a loop.
Range("tabelaClientes[Nome]").SpecialCells(xlCellTypeBlanks).EntireRow.Delete
Edit: To expand on my answer because I was in a hurry. SpecialCells mimic the menu that you will find in Excel after having pressed F5 and selected "Special cells... Blanks". This has the advantage of selecting all blanks at the same time and then delete the rows. Iteration can be very slow if your table is getting large thus this way will save a lot of time.
It does seem that you cannot delete multiple non-contiguous rows in a table. You can do either one of two things:
1- Convert back the table to a range and change the reference to a standard excel reference
2- Loop through the results of SpecialCells().
Option #2 will yield in slower code because of the loop but it will still be better than looping through all cells and check if they are blank but I can understand that you may need to keep it as a table.

How to conditionally copy and paste a from a table in one workbook to a table in another workbook in VBA

Although I am relatively seasoned excel user, I am fairly new to VBA and am trying to tackle a fairly complicated task (at least it's complicated to me).
I have data in tables in 5 workbooks that I am trying to aggregate into one master workbook. However, I don't want all of the data. I only want to pull the data ( about 6 columns worth) that failed one of the tests (cell reads: "Fail"). All of the source workbooks have the 6 columns in the same order and have say "Pass" or "Fail" in their own cells. I want to pull only the fails from each and paste into a master workbook. I would also like it to pull into a clean looking table (i.e no blank rows between each set of data).
I believe this is feasible, but it's above my skill level (right now). After hours and hours of research and trial and error that inevitably always ends in failure, I am about to wave the white flag. This is my last hope. Please help!
The approach would be to:
Open all the workbooks to merge (assumed to be done manually, but could be coded if required)
Get a reference to the Master Table
Loop through open workbooks
Find the Table in the current workbook (code below assumes onlt one Table in each book. IOf this is not the case, then it can be changed to use some distingusing feature of the required table)
Use AutoFilter to filter for "Fail" records.
Copy and Paste the data onto the end of the Master Table
This code demonstrates how to do this. You will need to adapt it to tour specific situation.
Place this code in a Module in the Master workbook.
Sub Demo()
Dim wb As Workbook
Dim ws As Worksheet
Dim lo As ListObject
Dim loMaster As ListObject
'Get Reference to Master table
Set loMaster = ThisWorkbook.Worksheets("Master").ListObjects(1)
' Loop through open workbooks
For Each wb In Workbooks
If wb.Name <> ThisWorkbook.Name Then
' Assumes only one Table in each workbook,
' so return the first one found
Set lo = Nothing
For Each ws In wb.Worksheets
If ws.ListObjects.Count > 0 Then
Set lo = ws.ListObjects(1)
Exit For
End If
Next
If Not lo Is Nothing Then
' Filter Table on column Result for Fail
lo.Range.AutoFilter _
Field:=lo.ListColumns("Result").Index, _
Criteria1:="Fail"
' Copy filterd data to Master Table
If loMaster.InsertRowRange Is Nothing Then
'Master table is not empty
lo.DataBodyRange.SpecialCells(xlCellTypeVisible).Copy _
loMaster.DataBodyRange.Cells(loMaster.DataBodyRange.Rows.Count + 1, 1)
Else
'Master table is empty
lo.DataBodyRange.SpecialCells(xlCellTypeVisible).Copy _
loMaster.InsertRowRange
End If
' Reset Autofilter
lo.Range.AutoFilter
End If
End If
Next
End Sub