Macro for auto monthy update

ExcelFind

New Member
Joined
Apr 6, 2023
Messages
8
Office Version
  1. 365
Platform
  1. Windows
Hello,

Can you help me out with a macro that only updates data in a table in case of a new month?

  • The data is automatically updated via a macro in columns AF1:AL1 (orange numbers)
  • In case current month+year = last populated month+year: nothing should happen
  • Only in case of a new month the script should to the following:
    • Add the next month with year (format MM/YY) at the end of column AE (extending the table)
    • Copy values AF1:AL1 to the new added row for the new month (AFx:ALx)
In the example below the macro should add month 04/23 in cell AE12 and copy/paste values AF1:AL1 to AF12:AL12.

1680785385386.png
 
Hello Jim,

Many thanks for your codes and write tips, this helps us a lot!

Huh? Does that mean that you were hoping for code that gets the "new" date and data before it is put into the table? But, I have no idea where that data comes from and how it gets there. My code assumes that the "new" data is already there!
Yes, the first part of our VBA code makes sure that the orange data is up-to-date (worksheets are updated from a external database). This orange data comes from different Pivot Tables and will be up-to-date. The requested code this thread should only add the orange data in Table1 in case of a "next" month/year. So if the user executes the script more times in the same month/year, the orange data should not be entered in the table if the data for that month/year already exists in Table1.

Unfortunately, because the spec you gave for the task did not specify that the date is in AN4 I wrote code that determines the "next" month/year after the last row's date month/year. That code always uses that "next" month/year rather than the date specified in AN4. So I'll have to rewrite. It'll take a while.
I did specify the "current" month/year indeed in AN4, as I was not sure how to cover this part in a code. It would indeed be better to have a code that determines the "next" month/year after the last row's date month/year. Could you edit this part of the code, so that the script always uses the "next" month/year rather then the date specified in AN4? This will also solve the problem with shifting columns, when extending the table in the future.

The code is working excellent and will save us a lot if time to update all tables in the workbook. However if I run the script twice the data is entered again in the Table for the same test date. Can you build a code that checks if the data is already entered for the current month/year and stops if the data is already present? Many thanks in advance!
 
Upvote 0

Excel Facts

Will the fill handle fill 1, 2, 3?
Yes! Type 1 in a cell. Hold down Ctrl while you drag the fill handle.
I hope that this does what you want. If today's month is the same as the month of the last date in the table then there is a message telling user that and no data is transferred. If so code skips to the next worksheet.

VBA Code:
Option Explicit
Option Base 1  '<= so arrays do not start at element zero.

' ----------------------------------------------------------------
' Procedure Name: TransferDataInWorksheets
' Purpose: Transfer data from range to table in specified sheets.
' Procedure Kind: Sub
' Procedure Access: Public
' Author: Jim
' Date: 4/13/2023
' Note: Transfers done are in the workbook containing this code (ThisWorkbook).
' ----------------------------------------------------------------

'This sub processes all sheets in which transfer of new data will occur.

Sub TransferDataInWorksheets()

    Dim wsToProcess As Worksheet
    
    Dim rTableRange As Range
    
    Dim iSheetsToProcessCount As Long
    
    Dim iSheet As Long
    
'   Array containing 1. sheet name, 2. "data from" range name or cell address (in the sheet),
'   3. table name (in the sheet) for each sheet to be processed.
    Dim asSheetsData() As String
    
'   Variable that holds the last date in the table
    Dim dLastDateInTable As Date
    
'   Count of sheets to process
    iSheetsToProcessCount = 2  '<= change to number of sheets to process.
    
'   Size the array to accommodate 3 data points for each sheet to process.
'   First array dimension is for 1. sheet name, 2. range name or address, 3. table name.
    ReDim asSheetsData(3, iSheetsToProcessCount)
    
'   Count of data rows in the table.
    Dim iTableRows As Long
    
    Dim sMsg As String
    
'   For each sheet to process need entries in the array like the following two.
'   ~~~ Sheet 1 ~~~
    asSheetsData(1, 1) = "Source2"   '<= name of first sheet to process
    asSheetsData(2, 1) = "AF1"       '<= cell location of first (leftmost) new data value
    asSheetsData(3, 1) = "Table3"    '<= name of table to process in the first sheet to process
    
'   ~~~ Sheet 2 ~~~
    asSheetsData(1, 2) = "Source3"
    asSheetsData(2, 2) = "AF1"
    asSheetsData(3, 2) = "Table4"
'
    For iSheet = 1 To iSheetsToProcessCount
        
'       Check for sheet specified exists. If not tell user.
        If Not WorksheetExists(asSheetsData(1, iSheet)) _
         Then
            MsgBox "The worksheet named " & asSheetsData(1, iSheet) & " does not exist.", vbExclamation
            GoTo NextIteration
        End If
                        
        Set wsToProcess = ThisWorkbook.Worksheets(asSheetsData(1, iSheet))
                        
'       Check valid address or range name exists in the sheet being processed. If not tell user.
        If Not IsValidCellAddress(asSheetsData(2, iSheet)) _
        And Not RangeNameExistsInSheet(asSheetsData(2, iSheet), wsToProcess) _
         Then
            MsgBox "Range " & asSheetsData(2, iSheet) & " does not exist in sheet named " & wsToProcess.Name & ".", vbExclamation
            GoTo NextIteration
        End If
        
'       Check table exists in the sheet being processed. If not tell user.
        If Not TableExistsInSheet(asSheetsData(3, iSheet), wsToProcess) _
         Then
            MsgBox "Table " & asSheetsData(3, iSheet) & " does not exist in sheet named " & wsToProcess.Name & ".", vbExclamation
            GoTo NextIteration
        End If
        
'       Check for "new" data exists. If not tell user.
        If wsToProcess.Range(asSheetsData(2, iSheet)).Cells(1).Value = "" _
         Then
            MsgBox "No new data exists in the sheet named " & wsToProcess.Name & ".", vbExclamation
            GoTo NextIteration
        End If
        
'       Point table object to thedata table
        Set rTableRange = wsToProcess.ListObjects(asSheetsData(3, iSheet)).Range
            
'       Get count of rows in the table before adding new data.
        iTableRows = rTableRange.Rows.Count

'       Grab the last date in the table.
        dLastDateInTable = rTableRange.Cells(1).Offset(iTableRows - 1)
            
'       Check month for the last date in data = today's date. If so skip to
'       the next iteration/worksheet to proess.
        If Month(dLastDateInTable) = Month(Now()) _
        Then
            sMsg = "Today's month and the month for the" _
                   & Chr(10) _
                   & "last date in the table are the same" _
                   & Chr(10) _
                   & "in the worksheet named " & wsToProcess.Name & "."
            
            MsgBox sMsg, vbExclamation
            
            GoTo NextIteration
        
        End If
        
'       Range ID is valid, worksheet exists, table exists,
'       there is new data and today's month <> last data month...
'       ...so transfer new data to the table. Parameters are 1. the worksheet sheet
'       (object) to process, 2. range (object) where "new" data exists,
'       and 3. the table (object) where "new" data is copied into.

        Call TransferDataToTable( _
         wsToProcess, _
         wsToProcess.Range(asSheetsData(2, iSheet)), _
         wsToProcess.ListObjects(asSheetsData(3, iSheet)))

NextIteration:
    
    Next iSheet

End Sub

VBA Code:
' ----------------------------------------------------------------
' Procedure Name: TransferDataToTableMY
' Purpose: Transfer month/year data from source range into specified table in specified sheet.
' Procedure Kind: Sub
' Procedure Access: Public
' Parameter pwsSheet (Worksheet): Worksheet (object) to be processed.
' Parameter prRangeToCopy (Range): Range (object) from data is transferred from.
' Parameter poTable (Object): Table object where data is transferred to.
' Author: Jim
' Date: 4/13/2023
' ----------------------------------------------------------------

Sub TransferDataToTable(pwsSheet As Worksheet, prRangeToCopy As Range, poTable As Object)

'   --------------------------
'         Declarations
'   --------------------------

'   Cell in the worksheet where the date for new data is located.
    Dim dPreviousDate As Date

'   Range object that will point to the existing table's cells range.
    Dim rTable As Range

'   Cells range where data is transferred to ("new" row in the table).
    Dim rRangeForPaste As Range
    
'   Count of table rows and columns.
    Dim iTableRows As Long
    Dim iTableCols As Long
    
'   ----------------------------
'         Initializations
'   ----------------------------

'   Range where table is located.
    Set rTable = poTable.Range

'   Count rows in the table before adding one and transferring data.
    iTableRows = rTable.Rows.Count

'   Count of columns in the table -- assume "new" data has the same
'   number of cells (width) as the table does.
    iTableCols = rTable.Columns.Count

    dPreviousDate = rTable.Cells(1).Offset(iTableRows).Value

'   Range of cells which "new" data is transferred FROM.
    Set prRangeToCopy = prRangeToCopy.Cells(1).Resize(1, iTableCols - 1)

'   Cells range into which data is transferred.
    Set rRangeForPaste = rTable.Cells(iTableRows + 1, 2).Resize(1, iTableCols - 1)
    
'   ---------------------------------------------
'          Copy the "New" Data To the Table
'   ---------------------------------------------

'   Transfer the "new" data TO the table in a new table row. Like copy/paste values.
'   FYI, doing this adds a row at the bottom of the table "automatically" (includes
'   formatting such as date formatted MM/YY.
    rRangeForPaste.Value = prRangeToCopy.Value
    
'   Put today's date into the first cell in the row for "new" data.
'   Offset(0, -1) means one to the left of the first cell with new data.
    rRangeForPaste.Cells(1).Offset(0, -1).Value = Now() 'dPreviousDate
        
'   => Add the line of code below if the data transferred should be cleared 
'   => after transfer (copy) to the table. Seems like a good idea...so that
'   => the same data is not transferred to the table twice. Remove the two
'   => single quote marks to implement.

'   Clear the data in the range containing the "new" data.
'    rRangeToCopy.Value = ""  '<= This line

End Sub
 
Upvote 0
This is a slightly newer version of the code that processes the various worksheets.

VBA Code:
Option Explicit
Option Base 1  '<= so arrays do not start at element zero.

' ----------------------------------------------------------------
' Procedure Name: TransferDataInWorksheets
' Purpose: Transfer data from range to table in specified sheets.
' Procedure Kind: Sub
' Procedure Access: Public
' Author: Jim
' Date: 4/13/2023
' Note: Transfers done are in the workbook containing this code (ThisWorkbook).
' ----------------------------------------------------------------

'This sub processes all sheets in which transfer of new data will occur.

Sub TransferDataInWorksheets()

    Dim wsToProcess As Worksheet
    
    Dim rTableRange As Range
    
    Dim iSheetsToProcessCount As Long
    
    Dim iSheet As Long
    
'   Array containing 1. sheet name, 2. "data from" range name or cell address (in the sheet),
'   3. table name (in the sheet) for each sheet to be processed.
    Dim asSheetsData() As String
    
'   Variable that holds the last date in the table
    Dim dLastDateInTable As Date
    
'   Count of sheets to process
    iSheetsToProcessCount = 2  '<= change to number of sheets to process.
    
'   Size the array to accommodate 3 data points for each sheet to process.
'   First array dimension is for 1. sheet name, 2. range name or address, 3. table name.
    ReDim asSheetsData(3, iSheetsToProcessCount)
    
'   Count of data rows in the table.
    Dim iTableRows As Long
    
    Dim sMsg As String
    
'   For each sheet to process need entries in the array like the following two.
'   ~~~ Sheet 1 ~~~
    asSheetsData(1, 1) = "Source2"   '<= name of first sheet to process
    asSheetsData(2, 1) = "AF1"       '<= cell location of first (leftmost) new data value
    asSheetsData(3, 1) = "Table3"    '<= name of table to process in the first sheet to process
    
'   ~~~ Sheet 2 ~~~
    asSheetsData(1, 2) = "Source3"
    asSheetsData(2, 2) = "AF1"
    asSheetsData(3, 2) = "Table4"
'
    For iSheet = 1 To iSheetsToProcessCount
        
'       Check for sheet specified exists. If not tell user.
        If Not WorksheetExists(asSheetsData(1, iSheet)) _
         Then
            MsgBox "The worksheet named " & asSheetsData(1, iSheet) & " does not exist.", vbExclamation
            GoTo NextIteration
        End If
                        
        Set wsToProcess = ThisWorkbook.Worksheets(asSheetsData(1, iSheet))
                        
'       Check valid address or range name exists in the sheet being processed.
'       If not tell user then process the next iteration/worksheet.
        If Not IsValidCellAddress(asSheetsData(2, iSheet)) _
        And Not RangeNameExistsInSheet(asSheetsData(2, iSheet), wsToProcess) _
         Then
            MsgBox "Range " & asSheetsData(2, iSheet) & " does not exist in sheet named " & wsToProcess.Name & ".", vbExclamation
            GoTo NextIteration
        End If
        
'       Check table exists in the sheet being processed. If not tell user
'       then process  the next iteration/worksheet.
        If Not TableExistsInSheet(asSheetsData(3, iSheet), wsToProcess) _
         Then
            MsgBox "Table " & asSheetsData(3, iSheet) & " does not exist in sheet named " & wsToProcess.Name & ".", vbExclamation
            GoTo NextIteration
        End If
        
'       Check for "new" data exists. If not tell user then process the next
'       iteration/worksheet to process.
        If wsToProcess.Range(asSheetsData(2, iSheet)).Cells(1).Value = "" _
         Then
            MsgBox "No new data exists in the sheet named " & wsToProcess.Name & ".", vbExclamation
            GoTo NextIteration
        End If
        
'       Point table object to the data table
        Set rTableRange = wsToProcess.ListObjects(asSheetsData(3, iSheet)).Range
            
'       Get count of rows in the table before adding new data.
        iTableRows = rTableRange.Rows.Count

'       Grab the last date in the table.
        dLastDateInTable = rTableRange.Cells(1).Offset(iTableRows - 1)
            
'       Check month for the last date in data = today's date. If so tell user
'       then process the next iteration/worksheet.
        If Month(dLastDateInTable) = Month(Now()) _
        Then
            sMsg = "Today's month and the month for the" _
                   & Chr(10) _
                   & "last date in the table are the same" _
                   & Chr(10) _
                   & "in the worksheet named " & wsToProcess.Name & "."
            
            MsgBox sMsg, vbExclamation
            
            GoTo NextIteration
        
        End If
        
'       Range ID is valid, worksheet exists, table exists,
'       there is new data and today's month <> last data month...
'       ...so transfer new data to the table. Parameters are 1. the worksheet sheet
'       (object) to process, 2. range (object) where "new" data exists,
'       and 3. the table (object) where "new" data is copied into.

        Call TransferDataToTable( _
         wsToProcess, _
         wsToProcess.Range(asSheetsData(2, iSheet)), _
         wsToProcess.ListObjects(asSheetsData(3, iSheet)))

NextIteration:
    
    Next iSheet

End Sub
 
Upvote 0
Hello Jim,

First of all sorry for the late response, I was not able to test the above new codes due to my holidays.

The script above is exactly what we wanted to achieve, this saves our team a lot of manual work and human errors.
This code works like a train, you're the very best! Many thanks for your help, I can't thank you enough for this.

Thank you from both myself and my team!
 
Upvote 0

Forum statistics

Threads
1,215,214
Messages
6,123,664
Members
449,114
Latest member
aides

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top