Home > Net >  Copy Cells from a table in another table in another sheet
Copy Cells from a table in another table in another sheet

Time:09-29

I got this table (which in another version, can have more/less columns, and in a different order, and inconsistent columns name), which usually is blank, but some id can have value like the one in the photo: I decided to use numeric label for the columns of the table (as the columns don't have fixed names, but can vary), in order to avoid this problem

enter image description here

I need to fill this table with data from the db sheet (which have the same properties as the table but have all the record)

The order of the data in the table and db, it's not the same, and the IDs in the table can be or not in the db (or vice-versa), but I have to fill only the ID that are in the table and have records in the db

For those Id that have some data in the table and dont have value in the db, I should clear them in the table and let blank. (I need to do this check and clean process, at least row by row, but if is better cell by cell x column) ie let assume that the record 1003 has some value in the table and not in the db, so I need to clear the entire row for this record and let it blank (ie the data in db are the latest data, if there are no data for this record in db, it should appear blank in the table).

For some reason, I can't do, select all the range of the table and clear the contents of it, because I have some limitations, this is why I need to do the clear row by row or cell by cell

enter image description here

As I mentioned I need first to match the columns of the table with those of db, and after making the search and after make the copy and paste. While doing this process I need to transform the format of the date in the db to match the format of the date in the table.

How can I do all this process with VBA, and which is the fastest way to do it?

CodePudding user response:

Please, test the next code. It follows the above explained scenario. Besides what I said in my comment, you must note that **NO other cell containing ONLY the string "id" must exist in both processed worksheets. The code should be fast, placing the ranges in arrays, swapping columns and processing only in memory:

Sub UpdateReport()
 Dim wsR As Worksheet, wsDB As Worksheet, lastRR As Long, lastRDB As Long, cellID As Range, cellID2 As Range
 Dim firstColR As Long, lastColR As Long, lastColDB As Long, firstColDB As Long, rngRep As Range, i As Long, j As Long
 Dim arrHR(), arrHDB(), arrR(), arrDB(), arrCols(), arrSwapped(), colDateNo, dateFormat As String, k As Long
 Const DateHeader As String = "bdate"
 
  Set wsR = Worksheets("Report")
  Set wsDB = Worksheets("db")
  
  '"Report" sheet extracting data:
  'find the cell containg "id" string, to determine the first table row/column:
  Set cellID = wsR.UsedRange.Find(what:="id", After:=wsR.UsedRange(1), LookIn:=xlValues, LookAt:=xlWhole)  'the cell where "id" was found
  If cellID Is Nothing Then MsgBox "No ""id"" header could be found in ""Report"" worksheet!": Exit Sub
  
   firstColR = cellID.Column     'first table column (in "Report" sheet)
   lastColR = wsR.cells(firstColR, wsR.Columns.count).End(xlToLeft).Column 'last table column
   lastRR = wsR.cells(wsR.rows.count, firstColR).End(xlUp).row                        'last row
   arrHR = wsR.Range(cellID, wsR.cells(cellID.row, lastColR)).Value2 'place the report table HEADER in an array
    colDateNo = Application.match(DateHeader, arrHR, 0) 'determine the column with Date number
    If Not IsError(colDateNo) Then
        'extract existing NumberFormat form the column keeping Dates
        dateFormat = getDateformat(wsR.cells(cellID.row, cellID.Column   colDateNo - 1), lastRR)
    Else
        MsgBox "Coundn't find any (necessary) column named """ & DateHeader & """...": Exit Sub
    End If
    
    'set the "Report" sheet range to be processed:
    Set rngRep = wsR.Range(cellID.Offset(1), wsR.cells(lastRR, lastColR))
    arrR = rngRep.Value2  'place the range in an array for faster iteration/processing

  '"DB" sheet extracting data:
  Set cellID2 = wsDB.UsedRange.Find(what:="id", After:=wsDB.UsedRange(1), LookIn:=xlValues, LookAt:=xlWhole)
  If cellID2 Is Nothing Then MsgBox "No ""id"" header could be found in ""db"" worksheet!": Exit Sub
  
   firstColDB = cellID2.Column 'first table column
   lastColDB = wsDB.cells(firstColDB, wsDB.Columns.count).End(xlToLeft).Column 'last table column
   lastRDB = wsDB.cells(wsDB.rows.count, firstColDB).End(xlUp).row                        'last table row
   arrHDB = wsDB.Range(cellID2, wsDB.cells(cellID2.row, lastColDB)).Value2          'place the DB table header in an array
   arrDB = wsDB.Range(cellID2.Offset(1), wsDB.cells(lastRDB, lastColDB)).Value2  'place the range to be processed in an array
   
   arrCols = colsOrderDB(arrHR, arrHDB)  'extract an array of CORRECT columns order, related to `Report` sheet table
   If arrCols(0) = "" Then Exit Sub 'if any header is missing, the code exits
   
   'create the array containing the columns in the NECESSARY order:
   arrSwapped = Application.Index(arrDB, Evaluate("row(1:" & UBound(arrDB) & ")"), arrCols)
  
  'process arrR array and fill its empty rows with data from the "id" sheet
  For i = 1 To UBound(arrR)
        If Application.CountA(rngRep.rows(i)) <> UBound(arrR, 2) Then 'check if NOT all the row is filled
           For j = 1 To UBound(arrSwapped)   'if not filled, iterate between the swapped array rows:
                If arrR(i, 1) = arrSwapped(j, 1) Then
                    For k = 2 To UBound(arrR, 2)
                        arrR(i, k) = arrSwapped(j, k) 'fill arrR with data from "db"
                    Next k
                    Exit For
                End If
           Next j
        End If
  Next i
  
  'drop the processed array content at once and format the date column as previously it was
  With rngRep
        .Value2 = arrSwapped
        .Columns(colDateNo).NumberFormat = dateFormat
  End With
  MsgBox "Ready..."
End Sub

Function colsOrderDB(arrR, arrDB) As Variant 'function to return the correct columns potition, related to "Report" sheet header
    Dim arrC(), mtch, i As Long
    ReDim arrC(UBound(arrR, 2) - 1)
    For i = 0 To UBound(arrR, 2) - 1
        mtch = Application.match(arrR(1, i   1), arrDB, 0)
        If Not IsError(mtch) Then
            arrC(i) = mtch
        Else
            MsgBox "The header """ & arrR(1, i   1) & """ does not exist in sheet ""db""!"
            colsOrderDB = Array(""): Exit Function
        End If
    Next i
    colsOrderDB = arrC
End Function

Function getDateformat(rng As Range, lastR As Long) As String 'function to return the NumberFormat of the colum keeping Date
    Dim rngDate As Range, i As Long
    Set rngDate = rng.Resize(lastR)
    For i = 1 To rngDate.rows.count
        If IsDate(rngDate(i)) Then getDateformat = rngDate(i).NumberFormat: Exit Function
    Next i
End Function

Please, send some feedback after testing it.

  •  Tags:  
  • vba
  • Related