I'm trying to come up with a tool to be able to consolidate row data into one line item in Excel. Below is an example:
I want to be able to consolidate record 0604, with the staggered data, into one line item across and remove the duplicates.
Note: this is a limited sample. The real data set can contain more columns (up to 60) with the possibility of 20 duplicate ID that are staggered and needs to be consolidated.
The software that I'm extracting the data from provide this as an output. I'm unable to channel this through a SQL software due to limited access. I know SQL will make this a bit easier, but I was wondering if this can be done in Excel.
Scan up the sheet and compare each cell with the one below and copy from below if blank. Delete row below if it has the same ID
Option Explicit
Sub consolidate()
Const SHEET_NAME = "Sheet1"
Const NO_OF_COLS = 30
Dim wb As Workbook, ws As Worksheet
Dim irow As Long, iLastRow As Long, c As Long, count As Long
Set wb = ThisWorkbook
Set ws = wb.Sheets(SHEET_NAME)
iLastRow = ws.Range("A" & Rows.count).End(xlUp).Row
' scan up sheet
For irow = iLastRow - 1 To 2 Step -1
' if same id below
If ws.Cells(irow + 1, 1) = ws.Cells(irow, 1) Then
' scan across
For c = 1 To NO_OF_COLS
' if blank copy from below
If Len(ws.Cells(irow, c)) = 0 Then
ws.Cells(irow, c) = ws.Cells(irow + 1, c)
End If
Next
ws.Rows(irow + 1).Delete
count = count + 1
End If
Next
MsgBox iLastRow - 1 & " rows scanned" & vbCr & _
count & " rows deleted from " & ws.Name, vbInformation
End Sub
If I understand right you could do this with the concatenate function in excel to combine all of the cells together in one cell.
I believe this is what you were asking?
This is an example of how to use that:
=CONCAT(A1,"-",B1)
And whatever cell this is typed into will have cell "A1-B1" as a value (with the values within those cells instead of the cell names).
Related
I am quite new to VBA so my question may sound silly to some of you.
I have a problem with my code. I am trying to check between 2 sheets(1st: test and 2nd: test data. In the code I am using the code name of the sheets) how may times a criteria/my product is met and based on that number to add that many rows beneath the SKU/product.
What I want to do is, if for my first product/SKU I have stock in 5 different locations, I want to add 5 rows in the first sheet and to see the qty in column D and the location in column E.
TestData tab
The reason why I need to list the quantity in different cells is that the stock is in different locations, so I can not just add in to one cell.
I am also adding screen shots of how my two sheets look like.
I have not add the loop to find the location yet, but I want to understand how to add the rows first.
Sub test()
Dim myrange As Range, testrange As Range, cell As Range, result As Range
Dim i As Long, testlastrow As Long, lastrow As Long
Dim helprng As Range
lastrow = TESTTAB.Range("a" & Rows.Count).End(xlUp).row
testlastrow = TDATA.Range("a" & Rows.Count).End(xlUp).row
Set testrange = TDATA.Range("a2:c" & testlastrow)
Set myrange = TESTTAB.Range("b2:b" & lastrow)
Set result = TESTTAB.Range("d2:e" & testlastrow)
Set helprng = TESTTAB.Range("f2:f" & lastrow)
For Each cell In myrange
For i = 1 To lastrow
If cell.Cells(i, 1) = testrange.Cells(i, 1) Then
result.Cells(i, 1) = testrange.Cells(i, 2)
End If
Next i
Next cell
End Sub
Here is the raw structure you were asking for.
Sub test()
' 011
Dim Rng As Range
Dim Tmp As Variant
Dim Radd As Long ' number of rows to add
Dim R As Long ' row counter
With Tdata
' Range, Cells and Rows Count, all in the same sheet
' exclude caption row(s)
Set Rng = .Range(.Cells(2, "A"), .Cells(.Rows.Count, "A").End(xlUp))
End With
Application.ScreenUpdating = False ' speed up the process
With TestTab
' end the loop in row 2 because row 1 might contain captions
' loop bottom to top because row numbers will change
' below the current row as you insert rwos
' column 1 = "A"
For R = .Cells(.Rows.Count, 1).End(xlUp).Row To 2 Step -1
Tmp = .Cells(R, 1).Value
Radd = Application.CountIf(Rng, Tmp)
If Radd > 1 Then
.Range(.Rows(R + 1), .Rows(R + Radd)).Insert
.Cells(R + 1, 1).Value = Radd ' for testing purposes
End If
Next R
End With
Application.ScreenUpdating = True ' now you look
End Sub
As our Evil Blue Monkey has suggested, inserting blank rows and then populating them may not be the most efficient way. You can copy a row and then click Insert to insert the copied data into a new row. Get the syntax from the Macro recorder if it's of interest. It works with the Range object the same way.
I'm trying to automate a list of data to be transferred to specific sheets by adding new rows, all within the same workbook.
Ideally I wouldn't like to limit the number of rows of data to be transferred as there could be a large amount of data coming in. I have tried the following code but it only works for a single row of data, can anyone help improve this code to transfer multiple rows?
Sub AddValues()
'Dimension variable and declare data type
Dim i As Single
'Save row number of cell below last nonempty cell
i = Worksheets("" & Range("A2")).Range("B" & Rows.Count).End(xlUp).Row + 1
'Save input values to selected worksheet
Worksheets("" & Range("A2")).Range("B" & i & ":P" & i) = _
Worksheets("Form").Range("B2:P10").Value
'Clear input cells
Worksheets("Form").Range("B2:P10") = ""
'Stop macro
End Sub
Sample output of what I hope it do:
Try this one:
EDITED. That one is the last version, fixin the shifting problems from the previous one.
I just add a few comments so in the future you can modify it easily.
Option Explicit
Sub AddValues()
'Dimension variable and declare data type
Dim i As Long 'Counter
Dim j As Long 'Counter
Dim NextRow As Long 'Last Row used
'Save input values to selected worksheet
For i = 2 To Worksheets("Form").UsedRange.SpecialCells(xlCellTypeLastCell).Row 'For Each Row on Sheet "Form"
'If there is no item still copied (Problem with merged cells)
If Worksheets(Range("A" & i).Value2).Cells(1048576, 2).End(xlUp).Row < 7 Then
For j = 2 To Worksheets("Form").UsedRange.SpecialCells(xlCellTypeLastCell).Column
Worksheets(Range("A" & i).Value2).Cells(7, j).Value2 = Worksheets("Form").Cells(i, j).Value2
Next j
'If there is just one item still copied (Problem with merged cells)
ElseIf Worksheets(Range("A" & i).Value2).Cells(1048576, 2).End(xlUp).Row = 7 Then
For j = 2 To Worksheets("Form").UsedRange.SpecialCells(xlCellTypeLastCell).Column
Worksheets(Range("A" & i).Value2).Cells(8, j).Value2 = Worksheets("Form").Cells(i, j).Value2
Next j
'For all remaining scenarios
Else
NextRow = Worksheets(Range("A" & i).Value2).Cells(1048576, 2).End(xlUp).Row
For j = 2 To Worksheets("Form").UsedRange.SpecialCells(xlCellTypeLastCell).Column
Worksheets(Range("A" & i).Value2).Cells(NextRow + 1, j).Value2 = Worksheets("Form").Cells(i, j).Value2
Next j
End If
Next i
'Clear input cells from B2 cell until the last Cell (not required to pay attention to the range)
Range(Cells(2, 2), Worksheets("Form").UsedRange.SpecialCells(xlCellTypeLastCell)) = ""
'End macro
End Sub
Hope it helps!
I need to build a report which lists products in column A and qty sold / revenue / units on hand in the next 3 columns. Something like this:
Products Qty Sold Revenue Units on Hand
-------- -------- ------- -------------
A 1 10 3
B 2 20 4
C 1 20 5
D 3 30 6
Ideally, i want to setup this report in a way that I can dump data in a data tab and have it populate here. I can easily set that up with a sumifs formula.
The problem i'm facing is: How do i deal with an expanding list of products in column A?
For example, next week there is a new product 'E' that has some sales and i need to be able to dynamically add it in. It'll be tough for me to add it in manually as, in the real report, there will be hundreds of products listed. I could setup a pivot table but i'm not comfortable doing that with the audience i'll be sharing the report with.
Let me know if this makes sense and if i need to provide any additional information to clarify this problem.
Thanks for your help, appreciate it!
If you don't want to use a pivot table, I'd say your best bet is to write a short macro to make sure every product on your data tab shows up in your report tag. For example:
Option Explicit
Sub CheckDataAndAddToReport()
Dim wsReport As Worksheet, wsData As Worksheet
Dim startRow As Long, endRow As Long, currRow As Long, addRow As Long
Dim missingCt As Long
Set wsReport = ActiveWorkbook.Sheets("Report") 'put the name of your Report sheet here
Set wsData = ActiveWorkbook.Sheets("Data") 'put the name of your Data sheet here
'startRow will be the first row with data in the data worksheet
startRow = 2
'set endRow to the last row with data in the data worksheet
endRow = wsData.Cells(wsData.Rows.Count, 1).End(xlUp).Row
'loop through all the rows of the data worksheet with data
For currRow = startRow To endRow
'check to see if the item on the current row is found in the reports page
If WorksheetFunction.CountIf(wsReport.Columns(1), wsData.Cells(currRow, 1).Value) = 0 Then
'if not, add it and the relevant formulas
addRow = wsReport.Cells(wsReport.Rows.Count, 1).End(xlUp).Row + 1
wsReport.Cells(addRow, 1).Formula = wsData.Cells(currRow, 1).Value
wsReport.Cells(addRow, 2).Formula = "" 'put whatever formulas you need to here
wsReport.Cells(addRow, 3).Formula = "" 'put whatever formulas you need to here
wsReport.Cells(addRow, 4).Formula = "" 'put whatever formulas you need to here
'keep a count of how many were added for reporting purposes
missingCt = missingCt + 1
End If
Next currRow
'show a message box with the results
If missingCt > 0 Then
MsgBox "A total of " & missingCt & " items were found in " & wsData.Name & " that were missing from " & wsReport.Name & " and were added.", _
vbInformation, _
"Results"
Else
MsgBox "No items were found to be missing from " & wsReport.Name & ".", _
vbInformation, _
"Results"
End If
End Sub
I have never used macros before, but can anyone tell what am I missing in the following macro, so the data from sheet 1 would be copied to the next available line in sheet 2? I have tried "LastRow","NextRow"commands, but I can't get it right. Any help would be great.
Sheets("Sheet1").Range("B2").Select
Selection.Copy
iRow = Worksheets("Sheet2").Cells(Rows.Count, 1).End(x1up).Row + 1
Sheets("Sheet2").Range ("B" & iRow)
ActiveSheet.Paste
Try either of these. It's xlup not x1up, and you weren't pasting to your destination cell (and Selects are unnecessary).
iRow = Worksheets("Sheet2").Cells(Rows.Count, 1).End(xlup).Row + 1
Sheets("Sheet1").Range("B2").Copy Sheets("Sheet2").Range ("B" & iRow)
or
iRow = Worksheets("Sheet2").Cells(Rows.Count, 1).End(xlup).Row + 1
Sheets("Sheet2").Range ("B" & iRow).value=Sheets("Sheet1").Range("B2").value
IN regards to this, I have the below code. However, my issue is that I have multiple versions of this macro running and pulling information to the same sheet. I need to be able to have the macro find the next row and not overwrite what is already on the page.
Sub Product_Value_In_Specific_Row()
Dim c As Range
Dim J As Integer
Dim Source As Worksheet
Dim Target As Worksheet
' Change worksheet designations as needed
Set Source = ActiveWorkbook.Worksheets("mongodb")
Set Target = ActiveWorkbook.Worksheets("Inputs")
J = 2 ' Start copying to row 1 in target sheet
For Each c In Source.Range("A2:A100") ' Do 1000 rows
If c = "Product" then
Source.Rows(c.Row).Copy Target.Rows(J)
J = J + 1
End If
Next c
End Sub
I have been getting around this by changing the "J = 2" line to few rows down, but my other sheets have varying amounts of rows and would like for them to just copy and paste into the inputs sheet and not overwrite each other.
I have a rather silly problem. I have a macro (linked to a button) which copies cells A1:A2 from one worksheet (namedFP) to another worksheet (Log). I intend to copy these 2 cells on the log sheet every time I hit the macro button. The problem I am facing right now is that when I use the button multiple times, these cells are getting copied over each other instead of using the next available row to paste the cells.
This is what I have now, and I tried changing the 'Rowcount+1' to 'RowCount+2' but that did not work. Any help is appreciated.
DHRSheet.Select
Range("A1:A2").Select
Selection.Copy
LogSheet.Select
RowCount = LogSheet.UsedRange.Rows.Count
Dim r As Integer
r = RowCount + 1
Dim infocell As Range
Set infocell = Cells(r, 1)
infocell.Select
ActiveSheet.Paste
infocell.Value = DHRSheet.Name & "$" & infocell.Value
DHRSheet.Select
ActiveWorkbook.Save
Is this what you are trying?
Sub Sample()
Dim LogSheet As Worksheet, DHRSheet As Worksheet
Dim lrow As Long
'~~> Change this as applicable
Set LogSheet = Sheets("Sheet1")
Set DHRSheet = Sheets("Sheet2")
With LogSheet
lrow = LogSheet.Range("A" & .Rows.Count).End(xlUp).Row + 1
DHRSheet.Range("A1:A2").Copy .Range("A" & lrow)
End With
End Sub
Here's a function I use that is very reliable and always returns the last row of a sheet without fail:
(possibly excessive for your simple use, but I always recommend it)
Public Function LastRowOfSheet(ByVal TestSheetNumber As Variant)
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Input: Sheet index # or Sheet name
' Output: Last row of sheet.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Dim intNumberOfRowsInWorksheet As Long
intNumberOfRowsInWorksheet = Sheets(TestSheetNumber).UsedRange.Rows.Count
intNumberOfRowsInWorksheet = intNumberOfRowsInWorksheet + Sheets(TestSheetNumber).UsedRange.Row - 1
LastRowOfSheet = intNumberOfRowsInWorksheet
End Function
And I'd clean up your above code and use something like this:
Sub Move2RowsToEnd()
Dim iNextRowOfOutput As Long
Dim iRowNumber As Long
'- use the function to find the last row of the output sheet. we'll be pasting to the first row after.
iNextRowOfOutput = (LastRowOfSheet("Log") + 1)
'- you can adjust this for loop to loop through additional cells if you need to paste more than 2 rows in the future.
For iRowNumber = 1 To 2
'- for each row of input (2 total) set the value of the output sheet equal to it.
Sheets("Log").Range("A" & iNextRowOfOutput).Value = Sheets("namedFP").Range("A" & iRowNumber).Value
iNextRowOfOutput = iNextRowOfOutput + 1
Next iRowNumber
'- not sure which of these you want to save (one or both)
Sheets("namedFP").Save
Sheets("Log").Save
End Sub
Just paste the function above or below the Subroutine and let me know if you have any issues or questions regarding the 'Move2RowsToEnd' code.