I am trying to learn vba and I have this list. For every NAME there will be an individual worksheet created. If the name of the worksheet match the name on the list I need to put the length in cell J1. I tried to use if ... elseif ... but knowing I have 430 different names the code will be too long what should I do? What alternative code can I use?
Sub length()
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
If ws.Name = "A" Then
ws.Activate
Range("J1").Select
ActiveCell.FormulaR1C1 = 4153
ElseIf ws.Name = "B" Then
ws.Activate
Range("J1").Select
ActiveCell.FormulaR1C1 = 2273
Next
MsgBox "DONE"
End Sub
Sub length()
Dim Cell as Range
For Each Cell In Range("Name")
On Error Resume Next
ThisWorkbook.Sheets(Cell.Value).Range("J1") = Cell.Offset(0, 1)
If Err.Number <> 0 Then Debug.Print "Sheet " & Cell & " wasn't found"
On Error GoTo 0
Next Cell
MsgBox "DONE"
End Sub
Range("Name") needs to be changed to refer to the real range with the sheet names.
On Error ... can be removed if you're sure that all mentioned worksheets exist.
Write Values to Worksheets From a List
This will loop through the list of names. There may be worksheets whose names are not on the list.
Adjust the name of the worksheet containing the list (Sheet1) and the column (A) and row (2) of the first name.
Option Explicit
Sub CopyLengths()
' Reference the workbook ('wb').
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
' Reference the source worksheet ('sws').
Dim sws As Worksheet: Set sws = wb.Worksheets("Sheet1")
' Calculate the last row ('slRow'), the row of the last non-empty cell
' in the worksheet names column.
Dim slRow As Long: slRow = sws.Cells(sws.Rows.Count, "A").End(xlUp).Row
' Reference the source range ('srg'), the one-column range
' containing the worksheet names.
Dim srg As Range: Set srg = sws.Range("A2", sws.Cells(slRow, "A"))
Dim dws As Worksheet ' Destination Worksheet
Dim sCell As Range ' Current Source (Name) Cell
Dim sString As String ' Current Source String
' Copy lenghts.
' Loop through the cells ('sCell') of the source range...
For Each sCell In srg.Cells
' Convert the current cell's value to a string ('CStr')
' and write the string to a variable ('sString').
sString = CStr(sCell.Value)
' Check if the string is not an empty string...
If Len(sString) > 0 Then ' the cell is not blank
' Attempt to reference the worksheet named after the string.
On Error Resume Next
Set dws = wb.Worksheets(sString)
On Error GoTo 0
If Not dws Is Nothing Then ' worksheet found (referenced)
' Copy (write) the length.
dws.Range("J1").Value = sCell.Offset(, 1).Value
Set dws = Nothing ' reset the variable
'Else ' worksheet not found (not referenced); do nothing or e.g. ...
'Debug.Print "Worksheet '" & sString & "' not found"
End If
'Else ' the cell is blank; do nothing
End If
Next sCell
' Inform.
MsgBox "Lengths copied.", vbInformation
End Sub
Sub UpdateSheets()
Dim vTable As Variant
Dim iRow As Long
' SHEET_NAME: The sheets name containing the table: Name, LENGTH
' RANGE: the range where the sheet names are listed (without the header)
' vTable: the table with 'Name' & 'LENGTH' column values in memory
vTable = ThisWorkbook.Worksheets("SHEET_NAME").Range("I2:J7").Value2
For iRow = LBound(vTable, 1) To UBound(vTable, 1) ' iRow: current row in table
' vTable(iRow, 1): 'Name' column value
' vTable(iRow, 2): 'LENGTH' column value
On Error Resume Next
ThisWorkbook.Worksheets(CStr(vTable(iRow, 1))).Range("J1").Value2 = vTable(iRow, 2)
On Error GoTo 0
If Err.Number <> 0 Then
' DO SOMETHING IF ERROR IS THROWN (CREATE MISSING WORKSHEET)
Err.Clear
End If
Next iRow
MsgBox "DONE"
End Sub
If you have any questions don't hesitate!
Cheers, Peter.
Assuming that the columns are as on the image, you can do this:
Sub fnPickLength()
Dim ws As Excel.Worksheet
Dim oCell As Excel.Range
Dim oRng As Excel.Range
Set oRng = Range("rngTheNames") 'name the range with this name
For Each ws In ThisWorkbook.Worksheets
For Each oCell In oRng
If UCase(ws.Name) = UCase(oCell.Value) Then
ws.Activate
Range("J1").Select
ActiveCell.FormulaR1C1 = oCell.Offset(0, 1).Value
Exit For
End If
Next
Next
MsgBox "DONE"
End Sub
Please adapt the named range as you want. I've choosen as "rngTheNames".
The ws name is compared with each oCell value. If matched, the Offset property reads the sibling cell of the evaluated name and put its value on the ws.
Related
Im trying to copy a table range with criteria, however I am not able to define the criteria to copy the desired lines, which consists of copying only the lines where the CC column has data skiping the entire row if CC is empty. I'll just copy ( copy to clipboard ), for paste I'll do it manually for other reasons
The lines will always be like this, never with a whole blank line between them like the second image
Sub CopyValues()
Application.ScreenUpdating = False
Dim rng As Range
Dim bottomA As Long
Dim srcWS As Worksheet
Set srcWS = Sheets("CC2")
With srcWS
bottomA = .Range("B" & .Rows.Count).End(xlUp).Row
For Each rng In .Range("B3:I3" & bottomA)
If WorksheetFunction.Sum(.Range("B" & rng.Row & ":I" & rng.Row)) > 0 Then
Range("B" & rng.Row & ":I" & rng.Row)).Copy
End If
Next rng
End With
Application.ScreenUpdating = True
End Sub
Use Union to select a non-contiguous range.
Option Explicit
Sub CopyValues()
Dim wb As Workbook, ws As Worksheet
Dim rng As Range, rngB As Range
Dim tbl As ListObject
Set wb = ThisWorkbook
Set ws = wb.Sheets("CC2")
With ws.ListObjects("Tabela452")
For Each rngB In .ListColumns("CC").DataBodyRange
If Len(rngB) > 0 Then
If rng Is Nothing Then
Set rng = rngB.Resize(1, 8) ' B to I
Else
Set rng = Union(rng, rngB.Resize(1, 8))
End If
End If
Next
End With
If rng Is Nothing Then
MsgBox "Nothing selected", vbExclamation
Else
rng.Select
rng.Copy
MsgBox "range copied " & rng.Address, vbInformation
End If
End Sub
Please, test the next adapted code. It does not need any iteration:
Sub CopyValues()
Dim rngCopy As Range, tbl As ListObject
Dim srcWS As Worksheet: Set srcWS = Sheets("CC2")
Set tbl = srcWS.ListObjects(1) 'use here the table name, if more than 1
On Error Resume Next 'for the case of no any value in the table first column
Set rngCopy = tbl.DataBodyRange.Columns(1).SpecialCells(xlCellTypeConstants)
'or
'Set rngCopy = tbl.DataBodyRange.Columns(tbl.ListColumns("CC").Index).SpecialCells(xlCellTypeConstants)
On Error GoTo 0
If Not rngCopy Is Nothing Then 'for the case of no any values in table first column
Intersect(rngCopy.EntireRow, tbl.DataBodyRange).Copy
Else
MsgBox "No any value in column ""CC""..."
End If
End Sub
As I said in my comment, it works if the values in column "CC" are not result of formulas...
Copy Filtered Rows From Excel Table (ListObject)
The screenshot illustrates the benefits of using an Excel table:
The table can be anywhere on the worksheet.
You can easily reference a column by its name (header).
You can move the column anywhere in the table.
Sub CopyFilteredRows()
' Define constants.
Const WorksheetName As String = "CC2"
Const TableName As String = "Tabela452"
Const CriteriaColumnName As String = "CC"
Const Criteria As String = "<>" ' non-blanks ('blank' includes 'empty')
' Reference the objects ('wb', 'ws' , 'tbl', 'lc')
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim ws As Worksheet: Set ws = wb.Worksheets(WorksheetName)
Dim tbl As ListObject: Set tbl = ws.ListObjects(TableName)
Dim lc As ListColumn: Set lc = tbl.ListColumns(CriteriaColumnName)
' Reference the filtered rows ('rrg').
Dim rrg As Range
With tbl
If .ShowAutoFilter Then ' autofilter arrows are turned on
' Clear all filters.
If .AutoFilter.FilterMode Then .AutoFilter.ShowAllData
Else ' autofilter arrows are turned off
.ShowAutoFilter = True ' turn on the autofilter arrows
End If
.Range.AutoFilter lc.Index, Criteria
' Attempt to reference the filtered rows ('rrg').
On Error Resume Next
' Reference the visible cells.
Set rrg = .DataBodyRange.SpecialCells(xlCellTypeVisible)
' When columns are hidden, resize to entire rows of the table.
Set rrg = Intersect(.DataBodyRange, rrg.EntireRow)
On Error GoTo 0
' Clear the filter.
.AutoFilter.ShowAllData
End With
' Invalidate the filtered rows.
If rrg Is Nothing Then
MsgBox "No filtered rows.", vbExclamation
Exit Sub
End If
' Copy.
rrg.Copy
End Sub
For the criteria when looking for empty values, you can always use LEN to check the number of characters in the cell.
If it is greater than 0 it means that something is in there, you can also set it to an exact amount of digits to be more precise.
Something like this should work:
Sub CopyValues()
Application.ScreenUpdating = False
Dim rng As Range
Dim bottomA As Long
Dim srcWS As Worksheet
Dim currentRow As Long
Const ccColumn As Long = 2
Const startingRow As Long = 3
Set srcWS = Sheets("CC2")
With srcWS
bottomA = .Range("B" & .Rows.Count).End(xlUp).Row
For currentRow = startingRow To bottomA
If Len(.Cells(currentRow, ccColumn).Value) > 0 Then
.Range("B" & currentRow & ":I" & currentRow).Copy
End If
Next currentRow
End With
Application.ScreenUpdating = True
End Sub
I have a worksheet. I want to clear the contents of cells 17-37, 45-60, 65-79; with the column being determined by the header (in Row 15) being equal to the value in Cell B1 of same worksheet. My sheet has columns C-Z to be looked at.
I tried to write a loop, or use other parts of code found online and I am unable to add the lookup so that it will only clear in the column if the value in row 15 of the column matches B1.
EDIT: Here is what I had so far, based on comments but it still will not find my value so cindex returns Error 2042 - checked for leading or trailing spaces.
Set ws to FORECAST
Dim ws As Worksheet
Set ws = ActiveWorkbook.Worksheets("FORECAST")
'Set range to search
Dim hrg As Range
Set hrg = ws.Range("C15:Z15")
'set range to clear contents
Dim crg As Range
Set crg = ws.Range("17:37,45:60,65:79")
'Set header value to find
Dim Header As Variant
Header = ws.Range("B1").Value
'hold column where match is found
Dim cIndex As Variant
cIndex = Application.Match(Header, hrg, 0)
'validate column index and clear
If IsNumeric(cIndex) Then
Intersect(hrg.Cells(cIndex).EntireColumn, crg).Clear
'else no match found; no nothing
End If
End Sub
Clear Cells When Matching Header
Sub ClearColumn()
' Worksheet
Dim ws As Worksheet: Set ws = ActiveSheet ' improve!
' Header Range
Dim hrg As Range: Set hrg = ws.Range("C15:Z15")
' Clear-Entire-Rows Range
Dim crg As Range: Set crg = ws.Range("17:37,45:60,65:79")
' Header (Value)
Dim Header As Variant: Header = ws.Range("B1").Value
' Column Index (index of the matching cell (column)
' of the Header range (if a match))
Dim cIndex As Variant: cIndex = Application.Match(Header, hrg, 0)
' Validate the Column index and clear.
If IsNumeric(cIndex) Then ' match found
Intersect(hrg.Cells(cIndex).EntireColumn, crg).Clear
'Else ' no match found; do nothing
End If
End Sub
Solution
Sub ClearByHeaderName()
Dim criteriaCell As Range
Dim headerCells As Range
Dim headerCell As Range
Dim isColumnCleared As Boolean
Set criteriaCell = Range("B1")
If criteriaCell.Value = "" Then
MsgBox "Provide column name in B1!", vbExclamation
End
End If
Set headerCells = Range("C15:Z15")
For Each headerCell In headerCells
If headerCell.Value = criteriaCell.Value Then
ClearDataCells headerCell
isColumnCleared = True
End If
Next
If isColumnCleared Then
MsgBox "Done!", vbInformation
Else
MsgBox "Cannot find column '" & criteriaCell.Value & "'!", vbExclamation
End If
End Sub
Private Sub ClearDataCells(headerCell As Range)
With headerCell.EntireColumn
.Rows("17:37").Clear
.Rows("45:60").Clear
.Rows("65:79").Clear
End With
End Sub
I want to display the values found in Column 1 of workbook1 that are not in column 1 of workbook2. I am treating the contents as strings for exact match. Some of the account numbers look alike, but are not because they have leading 0's that make it different.
Workbook1: Column I am referencing is "AccountID"
AccountID
001
002
003
4
5
6
7
8
9
10
Workbook 2 column I am referencing is "AccountID"
AccountID
1
2
3
5
6
7
8
Desired Result Unique values from workbook1 that are not in workbook2 put into a new sheet
AccountID
001
002
003
4
9
10
here is my code, but some of the returned values ARE in both workbooks. I want the values from Workbook1, column1 that are unique from values in Workbook2, columnn1.
'Method to show what AccountID is in Client Bill Info but not FDG Accounts.
Sub CompareCols()
'Disabling the screen updating.
Application.ScreenUpdating = False
'Declaring variables
Dim Rng As Range
Dim RngList As Object
Dim WB1 As Worksheet
Dim WB2 As Worksheet
Dim NWS As Worksheet
'Setting values to variables declared
Set WB1 = ThisWorkbook.Sheets("Detailed Bill Info")
Set WB2 = Workbooks("FDG Accounts.xlsx").Sheets("FDG Accounts")
Set RngList = CreateObject("Scripting.Dictionary")
Set NWS = Sheets.Add
'Loop to collect values that are in column A of this workbook
'that are not in column A of WB2
For Each Rng In WB2.Range("A2", WB2.Range("A" & Rows.Count).End(xlUp))
If Not RngList.Exists(CStr(Rng.Value)) Then
RngList.Add CStr(Rng.Value), Nothing
End If
Next
For Each Rng In WB1.Range("A2", WB1.Range("A" & Rows.Count).End(xlUp))
If Not RngList.Exists(CStr(Rng.Value)) Then
WB1.Cells(Rng.Row, 1).Interior.ColorIndex = 6
tmpstr = Rng.Value
NWS.Cells(Rng.Row, 1).Value = tmpstr
End If
Next
Application.ScreenUpdating = True
End Sub
Unique Strings in Dictionaries
Option Explicit
Sub IdentifyNewAccounts()
Const NewName As String = "New Accounts"
' Reference the source column range ('srg').
Dim swb As Workbook: Set swb = Workbooks("FDG Accounts.xlsx")
Dim sws As Worksheet: Set sws = swb.Worksheets("FDG Accounts")
Dim srg As Range
Set srg = sws.Range("A2", sws.Cells(sws.Rows.Count, "A").End(xlUp))
' Write the unique values from the source column range
' to the keys of the source dictionary ('sDict').
Dim sDict As Object: Set sDict = CreateObject("Scripting.Dictionary")
sDict.CompareMode = vbTextCompare ' case-insensitive
Dim sCell As Range
Dim sString As String
For Each sCell In srg.Cells
sString = CStr(sCell.Value)
If Len(sString) > 0 Then ' exclude blanks
sDict(sString) = Empty
End If
Next sCell
' Reference the destination column range ('drg').
Dim dwb As Workbook: Set dwb = ThisWorkbook ' workbook containing this code
Dim dws As Worksheet: Set dws = dwb.Worksheets("Detailed Bill Info")
Dim drg As Range
Set drg = dws.Range("A2", dws.Cells(dws.Rows.Count, "A").End(xlUp))
' Write the unique values from the destination column range,
' that are not in the 'keys' of the source dictionary, to the 'keys'
' of the destination dictionary ('dDict').
Dim dDict As Object: Set dDict = CreateObject("Scripting.Dictionary")
dDict.CompareMode = vbTextCompare ' case-insensitive
Dim durg As Range
Dim dCell As Range
Dim dString As String
For Each dCell In drg.Cells
dString = CStr(dCell.Value)
If Len(dString) > 0 Then ' the cell is not blank
If Not sDict.Exists(dString) Then ' not found in source dictionary
' Write the unique string to the destination dictionary.
dDict(dString) = Empty
' Combine the cells to be highlighted into a range union.
If durg Is Nothing Then ' first cell
Set durg = dCell
Else ' all but the first cell
Set durg = Union(durg, dCell)
End If
'Else ' the string was found in the source dictionary; do nothing
End If
'Else ' the cell is blank; do nothing
End If
Next dCell
Set sDict = Nothing ' the relevant data is in the destination dictionary
' Validate.
If durg Is Nothing Then ' or 'If dDict.Count = 0 Then'
MsgBox "No unique accounts found.", vbExclamation
Exit Sub
End If
' Write the unique strings from the destination dictionary to the
' destination array ('dData'), a 2D one-based one-column string array.
Dim drCount As Long: drCount = dDict.Count
Dim dData() As String: ReDim dData(1 To drCount, 1 To 1)
Dim dKey As Variant
Dim r As Long
For Each dKey In dDict.Keys
r = r + 1
dData(r, 1) = dKey
Next dKey
Set dDict = Nothing ' the relevant data is in the destination array
' Turn off screen updating (so far the worksheets were only read from).
Application.ScreenUpdating = False
' Highlight the cells meeting the criteria in one go.
durg.Interior.Color = vbYellow
' Add a new worksheet, the new destination worksheet ('ndws').
Dim ndws As Worksheet
' Attempt to reference it.
On Error Resume Next
Set ndws = dwb.Worksheets(NewName)
On Error GoTo 0
' Check if it was referenced (if it exists).
If Not ndws Is Nothing Then ' it exists
Application.DisplayAlerts = False ' to delete without confirmation
ndws.Delete
Application.DisplayAlerts = True
'Else ' it doesn't exist; do nothing
End If
' Add and reference it.
Set ndws = dwb.Worksheets.Add(After:=dwb.Sheets(dwb.Sheets.Count))
' Apply changes.
With ndws
.Name = NewName ' rename
.Range("A1").Value = "AccountID" ' write header
End With
' Reference the new destination (one-column) data range ('dnrg').
Dim ndrg As Range: Set ndrg = ndws.Range("A2").Resize(drCount)
' Write the unique strings from the destination array
' to the new destination range.
With ndrg
.NumberFormat = "#" ' format
.Value = dData ' write
.EntireColumn.AutoFit ' more format
End With
' Activate (select) the destination workbook.
If Not dwb Is ActiveWorkbook Then ' it's not active
dwb.Activate
'Else ' it's already active; do nothing
End If
' Save the destination workbook.
'dwb.Save
' Turn on screen updating (to see the changes behind the message box).
Application.ScreenUpdating = True
' Inform.
MsgBox "New accounts identified.", vbInformation
End Sub
Extra Characters
Based on the sample data you provided above it appears that your data contains extra white space on several Account Id's.
To fix this, use the Trim function to remove the white space. Make sure to do this when checking to see if the value exists in your dictionary, as well as when you are capturing the value as well.
Extra notes
tmpstr is a missing variable. It's best to use Option Explicit Statement to find this issue.
NWS.Cells(Rng.Row, 1).Value = tmpstr needs to have the cell formatted to text before applying this. This can be done with NWS.Cells(Rng.Row, 1).NumberFormat = "#"
The fix
Below is your code with the above changes:
' Method to show what AccountID is in Client Bill Info but not FDG Accounts.
Sub CompareCols()
'Disabling the screen updating.
Application.ScreenUpdating = False
'Declaring variables
Dim Rng As Range
Dim RngList As Object
Dim WB1 As Worksheet
Dim WB2 As Worksheet
Dim NWS As Worksheet
'Setting values to variables declared
Set WB1 = ThisWorkbook.Sheets("Detailed Bill Info")
Set WB2 = Workbooks("FDG Accounts.xlsx").Sheets("FDG Accounts")
Set RngList = CreateObject("Scripting.Dictionary")
Set NWS = Sheets.Add
'Loop to collect values that are in column A of this workbook
'that are not in column A of WB2
For Each Rng In WB2.Range("A2", WB2.Range("A" & Rows.Count).End(xlUp))
If Not RngList.Exists(Trim(CStr(Rng.Value))) Then
RngList.Add Trim(CStr(Rng.Value)), Nothing
End If
Next
For Each Rng In WB1.Range("A2", WB1.Range("A" & Rows.Count).End(xlUp))
If Not RngList.Exists(Trim(CStr(Rng.Value))) Then
WB1.Cells(Rng.Row, 1).Interior.ColorIndex = 6
Dim tmpstr As String ' Added Missing variable
tmpstr = Trim(Rng.Value)
' Format will be lost on new cell
' Make sure to update it to text before
' setting the value
NWS.Cells(Rng.Row, 1).NumberFormat = "#"
NWS.Cells(Rng.Row, 1).Value = tmpstr
End If
Next
Application.ScreenUpdating = True
End Sub
I am currently using this code which goes through my worksheet and checks in the range O15:O300 to see if there are any cells that match the current date. If there is then it copies the entire row to worksheet "Today's Actions" then copies the site number (Situated in cell C3) to column AA in "Todays Actions".
I use the below code which works fine for this task for one specific sheet:
Sub rangecheck()
Application.ScreenUpdating = False
For Each cell In Range("O15:O300")
If cell.Value = Date Then
matchRow = cell.Row
Rows(matchRow & ":" & matchRow).Select
Selection.Copy
Sheets("Today's Actions").Range("A" & Rows.Count).End(xlUp).Offset(1, 0).PasteSpecial xlPasteValues
ActiveSheet.Range("C3").Copy
Sheets("Today's Actions").Range("AA" & Rows.Count).End(xlUp).Offset(1, 0).PasteSpecial xlPasteValues
End If
Next
Application.ScreenUpdating = True
End Sub
However, there are multiple sheets that I need to action this code for. So I use the below code to run this across all sheets:
Sub rangecheck_Set()
Dim ws As Worksheet
Dim starting_ws As Worksheet
Set starting_ws = ActiveSheet
Application.ScreenUpdating = False
For Each ws In ThisWorkbook.Worksheets
ws.Activate
Call rangecheck
Next
starting_ws.Activate 'activate the worksheet that was originally active ("Today's Actions")
Application.ScreenUpdating = True
End Sub
This issue I'm having is that it seems to work fine but randomly whenever there are a lot of dates that match todays date in range O15:O300, it duplicates some lines up to or slightly exceeding 300 rows (So as an example, if there were 15 rows that 'should' be brought back to "Today's action" tab, it would bring them back but then have a few other rows randomly duplicated down to around row 300).
I get this might be due to the range going down to 300 but I even edited the range to go to 'last row' and it still brings back the same issue. Any thoughts? I've been trying to solve this for days now. Any help appreciated
Don't use implicit references to worksheets and ranges. It is most likely that this is the reason for your problem.
Also you don't need to select and copy - another source for unforeseeable errors.
Another reason for your error could be that you don't exclude "Today's Actions"-sheet from the copying routine.
I re-wrote your sub that is copying the data:
Sub copyTodaysRows(wsSource As Worksheet, wsTarget As Worksheet)
If wsSource is wsTarget then Exit Sub 'don't run this for the target sheet
Dim c As Range, wsTargetNewRow As Long
For Each c In wsSource.Range("O15:O300")
If c.Value = Date Then
With wsTarget
wsTargetNewRow = .Range("A" & .Rows.Count).End(xlUp).Row + 1
c.EntireRow.Copy Destination:=.Range("A" & wsTargetNewRow)
.Range("AA" & wsTargetNewRow).Value = wsSource.Range("C3").Value
End With
End If
Next
End Sub
It takes the source sheet and the target sheet as input parameters.
You will call it like this within your "outer" routine:
Sub rangecheck_Set()
Application.ScreenUpdating = False
Dim wsSource as worksheet
Dim wsTarget as worksheet
Set wsTarget = Thisworkbook.Worksheets("Today's Actions")
For Each wsSource In ThisWorkbook.Worksheets
copyTodaysRows wsSource, wsTarget
Next
Application.ScreenUpdating = True
End Sub
Copy Values of Criteria (Dates) Rows From Multiple Worksheets
Option Explicit
Sub RetrieveTodaysActions()
' Calls 'RetrieveTodaysActionsCall'.
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim sws As Worksheet
For Each sws In ThisWorkbook.Worksheets
RetrieveTodaysActionsCall sws
Next sws
MsgBox "Today's actions retrieved.", vbInformation
End Sub
Sub RetrieveTodaysActionsCall(ByVal sws As Worksheet)
' Define constants.
' Source
Const sCriteriaColumnAddress As String = "O15:O300"
Const sCol1 As String = "A"
Const sCell2Address As String = "C3"
' Destination
Const dName As String = "Today's Actions"
Const dCol1 As String = "A"
Const dCol2 As String = "AA"
' Both
' Write the criteria date to a variable ('CriteriaDate').
Dim CriteriaDate As Date: CriteriaDate = Date ' today
' Exclude the destination worksheet.
If StrComp(sws.Name, dName, vbTextCompare) = 0 Then Exit Sub
' Reference the source criteria column range ('scrg').
Dim scrg As Range: Set scrg = sws.Range(sCriteriaColumnAddress)
' Check the number of matches, the number of rows to be copied
' to the destination worksheet.
If Application.CountIf(scrg, Date) = 0 Then Exit Sub
' Reference the range ('surg'), the range from the first cell
' in the source column ('sCol1') to the last cell of the used range.
Dim surg As Range
With sws.UsedRange
Set surg = sws.Range(sCol1 & 1, .Cells(.Rows.Count, .Columns.Count))
End With
' Reference the source range ('srg').
Dim srg As Range: Set srg = Intersect(scrg.EntireRow, surg)
If srg Is Nothing Then Exit Sub
' Write the number of columns of the source range to a variable (cCount).
Dim cCount As Long: cCount = srg.Columns.Count
' Write the criteria column number to a variable ('CriteriaColumn').
Dim CriteriaColumn As Long: CriteriaColumn = scrg.Column
' Write the values from the source range to an array ('Data').
Dim Data() As Variant: Data = srg.Value
Dim sValue As Variant ' Criteria Value in the Current Source Row
Dim sr As Long ' Current Source Row
Dim c As Long ' Current Source/Destination Column
Dim dr As Long ' Current Destination Row
' Loop through the rows of the array.
For sr = 1 To UBound(Data, 1)
' Write the value in the current row to a variable.
sValue = Data(sr, CriteriaColumn)
' Check if the current value is a date.
If IsDate(sValue) Then
' Check if the current value is equal to the criteria date.
If sValue = CriteriaDate Then
dr = dr + 1
' Write the values from the source row to the destination row.
For c = 1 To cCount
Data(dr, c) = Data(sr, c)
Next c
End If
End If
Next sr
' Reference the destination worksheet ('dws').
Dim dws As Worksheet: Set dws = sws.Parent.Worksheets(dName)
' Reference the destination first cell ('dfCell').
Dim dfCell As Range
Set dfCell = dws.Cells(dws.Rows.Count, dCol1).End(xlUp).Offset(1)
' Reference the destination range ('drg').
Dim drg As Range: Set drg = dfCell.Resize(dr, cCount)
' Write the values from the array to the destination range.
drg.Value = Data
' Reference the destination range 2 ('drg2').
Dim drg2 As Range: Set drg2 = drg.EntireRow.Columns(dCol2)
' Write the source cell 2 value to the destination range 2 ('drg2')
' (the same value to all cells of the range).
drg2.Value = sws.Range(sCell2Address).Value
End Sub
My process was different from the other responses, so I will still post it. I have also added a way of logging that a row has been logged because otherwise I saw that rows could be duplicated to the "Today's Actions" sheet.
Sub rangecheck(ByVal checkedSheet As Worksheet)
'#PARAM checkedSheet is the sheet to iterate through for like dates.
'Instantiate counter variables
Dim matchRow As Integer
matchRow = 0
Dim pasteRow As Integer
pasteRow = 0
Application.ScreenUpdating = False
For Each cell In checkedSheet.Range("O15:O300")
If cell.Value = Date Then
matchRow = cell.Row
'Checks if the row has been logged already (I use column "A" because I
'have no data in it, but this can be amy column in the row)
If checkedSheet.Cells(matchRow, 1) = "Logged" Then
'Do nothing
Else
'Sets value of "pasteRow" to one lower than the lowest used row in
column "AA"
pasteRow = Sheets("Today's Actions").Cells(Rows.Count,
27).End(xlUp).Row + 1
'Copies the values of the matchRow to the pasteRow
Sheets("Today's Actions").Rows(pasteRow).Value =
checkedSheet.Rows(matchRow).Value
'Copies the value of the Site Number to the paste row column "AA"
Sheets("Today's Actions").Cells(pasteRow, 27).Value =
checkedSheet.Cells(3, 3).Value
'Log that a row has been added to the "Today's Actions" sheet
checkedSheet.Cells(matchRow, 1) = "Logged"
End If
End If
Next
Application.ScreenUpdating = True
End Sub
I have also modifed your sub which calls the copying sub to check if it is trying to copy the "Today's Actions" sheet.
Sub rangecheck_Set()
Dim ws As Worksheet
Dim starting_ws As Worksheet
Set starting_ws = Worksheets("Today's Actions")
Application.ScreenUpdating = False
For Each ws In ThisWorkbook.Worksheets
'Check if the ws to check is "Today's Actions"
If ws.Name = "Today's Actions" Then
'Do Nothing
Else
Call rangecheck(ws)
End If
Next
starting_ws.Activate 'activate the worksheet that was originally active
Application.ScreenUpdating = True
End Sub
So I have a worksheet called "gar_nv" containing in its first row some strings that I'd like to define as names for my columns. For instance, first cell of column A is "Number", I'd like to refer to the column A(starting from the second cell) as "Number" instead of column "A".
Sub NameCol()
Dim LastRow As Long
Dim x As Long, Rng As Range
With gar_nv
For x = 1 To .UsedRange.Columns.Count
LastRow = Cells(Cells.Rows.Count, x).End(xlUp).Row
Set Rng = Cells(2, x).Resize(LastRow)
.Names.Add Name:=Cells(1, x), RefersTo:=Rng
Set Rng = Nothing
Next
End With
End Sub
When I test my code like this, it throws a 91 error, what am I doing wrong?
Sub test()
With gar_nv
For Each Rng In .Range("Number")
MsgBox (Rng.Value)
Next
End With
End Sub
Create Names for Columns of Data
gar_nv is the code name of a worksheet in the workbook containing this code.
Option Explicit
Sub NameColumnsData()
' Delete all previous names in the worksheet.
'DeleteAllWorksheetNames gar_nv
Dim hrg As Range ' header range
Dim drg As Range ' data range
Dim cCount As Long ' number of columns
With gar_nv.UsedRange
Set hrg = .Rows(1)
Set drg = .Resize(.Rows.Count - 1).Offset(1)
cCount = .Columns.Count
End With
Dim crg As Range
Dim c As Long
Dim cTitle As String
For c = 1 To cCount
cTitle = hrg.Cells(c).Value
Set crg = drg.Columns(c)
gar_nv.Names.Add cTitle, crg
' Of course, you can lose the variables and just do:
'gar_nv.Names.Add hrg.Cells(c).Value, drg.Columns(c)
Next c
MsgBox "Column data names created.", vbInformation
End Sub
Sub NameColumnsDataTEST()
Dim cCell As Range
With gar_nv
For Each cCell In .Range("Number").Cells
' Caution! If there are many cells it may take 'forever'.
'MsgBox cCell.Address(0, 0) & ": " & cCell.Value
' Rather print to the Immediate window (Ctrl+G):
Debug.Print cCell.Address(0, 0) & ": " & cCell.Value
Next
End With
End Sub
Sub DeleteAllWorksheetNames(ByVal ws As Worksheet)
Dim nm As Name
For Each nm In ws.Names
Debug.Print nm.Name, nm.RefersTo, "Deleted!"
nm.Delete
Next nm
End Sub