VBA to concatenate and then increment resulting value based on another value - vba

I am trying to write a macro to loop through a spreadsheet, and on each row, concatenate three values (from different columns) into a single value (integer), and result that in another column on the same row. Then, increment from that number, based on the number from a different value in the column. Each iteration of this (including the first one) should copy the first column's value from that row, so that each increment reflects the same information in the newly created output.
Here's an example of the input data:
B2, C2, and D2 should all be concatenated, resulting in the number 5555551000, and that should be placed in cell I2. A2 should be copied to H2, as I2's location identifier. I2 should then be incremented based on the value of F2 (in this case, 10 times), and those results should be iterated under I2 starting at I3, with A2's value to the left of each output's cell, in the corresponding H column.
Here's an example of the output on the same sheet:
Once the output completes for expanding the first range of numbers, the loop continues to the next row and repeats the process.
I took a stab at this by setting the starting point, then doing a for loop with row.Count and inside of this, doing a Do While loop and breaking the loop based on the DID integer. I'm not having much success and perhaps it has to do with the way I'm using ActiveCell to try to move around during the iterations.
Any suggestions would be appreciated. I'm not allowed to embed pictures yet, thus the external links to the examples.

Like others have pointed out, its a lot easier to understand and troubleshoot what you're trying to do when you post the code, but I took a stab at it and came up with the following- quick note, this sub takes place on 2 different sheets (the source sheet, and then the resulting output sheet). If you really need it on the same sheet then I guess you could output the data right on top of the old data.
Public Sub sampleSub()
Dim sourceWS As Worksheet
Dim sourceData() As Variable
Dim outputRange As Range
Dim outputArr() As Variable
Dim readCounter As Long
Dim writeCounter As Long
Dim iterationCounter As Long
Set sourceWS = ThisWorkbook.Sheets(1)
sourceData = sourceWS.Range("A2:F4").Value2 'Read in source data
'Redim outout array with enough rows to be able to store each iteration (column F => 10 + 120 + 1000...)
ReDim outputArr(1 To Application.WorksheetFunction.Sum(sourceWS.Range("F2:F4")), 1 To 9)
For readCounter = 1 To UBound(sourceData, 1) 'Loop through each row of source data
For iterationCounter = 0 To sourceData(readCounter, 6) - 1 'Iterates to # in source data column F
writeCounter = writeCounter + 1
outputArr(writeCounter, 1) = sourceData(readCounter, 1) 'Write source data column A to output column A
outputArr(writeCounter, 2) = sourceData(readCounter, 2) 'Write source data column B to output column B
outputArr(writeCounter, 3) = sourceData(readCounter, 3) 'Write source data column C to output column C
outputArr(writeCounter, 4) = sourceData(readCounter, 4) 'Write source data column D to output column D
outputArr(writeCounter, 5) = sourceData(readCounter, 5) 'Write source data column E to output column E
outputArr(writeCounter, 6) = sourceData(readCounter, 6) 'Write source data column F to output column F
outputArr(writeCounter, 7) = sourceData(readCounter, 7) 'Write source data column G to output column G
outputArr(writeCounter, 8) = sourceData(readCounter, 1) 'Write source data column A to output column H
'Concatonate source data columns B, C & D and then adds iteration counter
outputArr(writeCounter, 9) = CLng(sourceData(readCounter, 2) & sourceData(readCounter, 3) & sourceData(readCounter, 4)) + iterationCounter
Next
Next
'User selects target range and then data is outputted
Set outputRange = Application.InputBox("Select target for output:", Type:=8)
outputRange.Resize(UBound(outputArr, 1), UBound(outputArr, 2)) = outputArr
End Sub
Hope this helps,
TheSilkCode

Related

Multiply columns of Excel table using VBA

I am trying to multiply values in two columns of a table and display it in another column.
Since this process has to be repeated for multiple columns, how should I go about referencing columns using column headers? Any help would be appreciated.
The logic would be as follows:
ListColumns(x) = ListColumns(x - 1) * ListColumns(x - 3)
This is within a loop where the value of x changes.
There are multiple ways of achieving what you are after.
1st: Let's suppose x = 4, so you want to multiply column A and C and store result in D column. Simply put formula = A1 * C1 in D1 and drag it all the way down.
2nd: Using VBA, more generic:
Sub MultiplyCoulmns()
Dim resultColumn As Long 'this is x
resultColumn = 4 'just for example, change it to whatever you need
'alternatively, specify column header
Dim header As String
header = "SomeColumn"
resultColumn = Application.WorksheetFunction.Match(header, Range("A1:Z1"), 0)
Dim i As Long, lastRow As Long
lastRow = Cells(Rows.Count, resultColumn).End(xlUp).Row
For i = 1 To lastRow
Cells(i, resultColumn) = Cells(i, resultColumn - 1) * Cells(i, resultColumn - 3)
Next
End Sub

Macro to Consolidate names and add quantities from multiple columns

I have an Excel template that I am working on as a tool for our department, and it has multiple sheets that can be copied, and what it ultimately does, is compile data from the first few sheets to create a list of sheet goods to be produced in our manufacturing facility. Each line item consists of a quantity, and then a core material, and two faces. This list is a separate sheet, that can be copied to create many different lists all referencing data from the same first three sheets.
I need to be able to quickly, and in a somewhat automated process, create a secondary list from the data of the first list. The secondary list needs to tell give me a total of each unique core, face, and backer. Some of the backers are the same as the face, so those should be consolidated.
I have a macro already that can allow the user to select a range of data, and then it spits out a consolidated list with quantities and names. The problem is this only works for 3 columns of data, and uses the 3rd column as the name, and the first as the quantity. I haven't figured out how to get it to look to columns of data that are not exactly adjacent, or more than 3 columns.
I am much more comfortable with spreadsheet formulas, but I'm thinking a macro would be the best solution if I can figure it out, as the end users of this spreadsheet have limited knowledge of excel, and I don't want to rely on them memorizing a bunch of steps.
First List
Start of Second List
Here is the macro I have so far.
Sub Macro1()
Dim i, J, K, L, M, R1, R1F, C1F, Temp As Integer
Dim SemiFinalData(500, 2) As Variant
Dim FinalData(500, 2) As Variant
i = J = 0
Set InputData = Application.InputBox(prompt:="Select the full range of Data (Qty Through Description)", Type:=8)
R1 = InputData.Rows.Count 'Gets Data to Summarize and Counts the Number of Rows
For i = 1 To R1
If InputData(i, 3) <> "" Then
SemiFinalData(J, 0) = InputData(i, 1)
SemiFinalData(J, 1) = InputData(i, 2)
SemiFinalData(J, 2) = InputData(i, 3)
J = J + 1
End If
Next i 'Extracts Non-Blank Data into Array
M = 0
For i = 0 To J - 1 'Loops for each value in SemifinalData
L = 0
For K = 0 To J - 1 'Second loop for each value in SemifinalData
If SemiFinalData(i, 2) = FinalData(K, 2) Then 'Counter for Duplication Test
L = L + 1
End If
Next K
If L < 1 Then 'Tests for Duplication and Extracts Data to FinalData Array
FinalData(M, 1) = SemiFinalData(i, 1)
FinalData(M, 2) = SemiFinalData(i, 2)
M = M + 1
End If
Next i
For i = 0 To M - 1
Temp = 0
For K = 0 To J - 1
If FinalData(i, 2) = SemiFinalData(K, 2) Then
Temp = Temp + SemiFinalData(K, 0)
End If
Next K
FinalData(i, 0) = Temp
Next i
Set OutputData = Application.InputBox(prompt:="Select the first Cell of Output Range (for Qty)", Type:=8)
R1F = OutputData.Row
C1F = OutputData.Column 'Gets Row/Column for Start of Output Range
For K = 0 To 2
Cells(R1F, C1F + K).Select
For i = 0 To M - 1
Selection = FinalData(i, K)
ActiveCell.Offset(1, 0).Range("A1").Select 'Writes Data to Sheet
Next i
Next K
End Sub
Essentially I am struggling with the 3 types of data on the same row from the first list, and the best way to separate them onto their own line on the second sheet.
You may want to look at using
Worksheets().range().AdvancedFilter(....)
This could help you pick out the data that you are looking for much easier. Check the office vba reference for more details.

Create a single column of an Excel table (zeroes excluded)

I have an Excel table.
And I need to write its data into a single column, row by row, every row is "read" from left to right, zeroes excluded. Please look at the picture to understand better:
Is there a way to do it quickly using VBA? I tried using only formulas and it worked, but it took several steps (creating a column, excluding zeroes, re-writing the column...) and really slowed down the whole process.
To copy all the non empty values from a range to a single column:
Dim source(), arr(), r&, c&, i&
' read the data from the range
source = [A1:G3].Value2
' copy the non empty value
ReDim arr(1 To UBound(source, 1) * UBound(source, 2), 1 To 1)
For r = 1 To UBound(source, 1)
For c = 1 To UBound(source, 2)
If source(r, c) <> Empty Then
i = i + 1
arr(i, 1) = source(r, c)
End If
Next
Next
' write the data back to the sheet
[A7].Resize(i, 1) = arr

Looping until blank column

I am putting together some VBA code which i think needs a loop. Loops are often my biggest weakness with VBA and I need some assistance.
I have a text file which i import into an excel spreadsheet. The length of how many columns and rows and down will vary day to day.
For example today's file might have data in columns A - H, tomorrow it might be A : P. Each typical row count will be around the 200 mark, so not to long.
In essence im trying to make one long list in column A from all the data spread over multiple columns.
Im looking for a loop that checks if the column has data in it, if it does it then copies the data into the bottom of the data in column A.
So for illustration purposes say the data goes out to column G, it will copy B1, xl down, find the first empty row in A and paste, then do the same for C, stopping after column G.
I hope I’ve been clear when writing this.
Thanks in advance
Matt
You first want to loop over all columns. So a FOR loop from column B to LastColumn (which there is a function for.) Then you want to loop through all rows within that column to find the first empty row, and then substract one to arrive at the last column with data.
If Cells(row,col) = "" Then
LastRowCopy = row -1
Then you want to copy everything to A1, and keep track of the last row you posted in. So you want to have a variable that counts. Something like:
LastRowPaste = LastRowPaste + row
I could write the code for it, but perhaps you learn more by figuring it out yourself.
Edit: Also perhaps an interesting read on finding last rows and or columns is this: http://www.rondebruin.nl/win/s9/win005.htm
Edit2: You could ofcourse also use the same for finding the last column as the method I used for finding the last row. Then you just loop through the columns and see if:
If Cells(1, col) = "" Then
LastCol = col -1
Edit3:
I wrote out the entire code:
Sub copypaste()
Dim LastRowCopy As String
Dim LastRowPaste As String
Dim LastCol As String
Dim col As Integer
Dim row As Integer
LastCol = ActiveSheet.UsedRange.Columns.Count
LastRowCopy = ActiveSheet.UsedRange.Rows.Count
LastRowPaste = ActiveSheet.UsedRange.Rows.Count
For row = 1 to LastRowPaste
If Cells(row, 1) = "" Then
LastRowPaste = row
Exit For
End if
Next row
For col = 2 To LastCol
If Application.WorksheetFunction.CountA(Columns(col)) = 0 Then
LastCol = col -1
End If
Next col
For col = 2 To LastCol
For row = 1 To LastRowCopy
If Not Cells(row, col) = "" Then
Cells(LastRowPaste, 1) = Cells(row, col)
LastRowPaste = LastRowPaste + 1
End If
Next row
Next col
End Sub

Compare given cells of each row of two tables

I am looking to update the last column of one data table with the last column of another data table. This is part of a bigger vba code. The first table spreads from A2 to column K and row "lastrpivot1". The second goes from A1001 to column K and row "lastrpivot2". Beginning with the first row of table 2 (row1001) i have to find the equivalent row in table 1 based on the values in cells A to E.
So cells A to E or frow 1001 have to be compared to cells A to E of row 2, then row 3, then row 4... until a match if found or until row "lastrpivot1". When a match is found, the value in K must return to the K value of row 1001. EX: if AtoE of row 1001 match row AtoE of row 65, then copu K65 to K1001. there shound not be more than 1 match from each table. and if there is no match there is nothing to return.
Then we start this all over for row 1002 (second row of second chart), then 1003, 1004... to lastrpivot2.
I do use vba but i do not know all the functions. this is probably why i cant figure this out.
Thnka you
In Cell K1001, try this:
=IF((A1001&B1001&C1001&D1001&E1001)=(A1&B1&C1&D1&E1),K1,"")
Then drag the formula down.
This compares the entire row 1001 to the entire row 1, which is what you're asking for.
If you intend to find the matching row like a VLOOKUP (you kind of imply this, but it is not clear that this is your intention) then you will need to use VBA to do this.
Something like (untested):
Sub MatchTables()
Dim tbl1 as Range, tbl2 as Range
Dim var1() as Variant, var2() as Variant, v as Variant
Dim r as Long, matchRow as Long
Set tbl1 = Range("A1:K500") '## Modify as needed
Set tbl2 = Range("A1001:K15001") '## Modify as needed
ReDim var1(1 to tbl1.Rows.Count)
ReDim var2(1 to tbl2.Rows.Count)
'## store the range values, conctaenated, in array variables:
For r = 1 to tbl1.Rows.Count
var1(r) = tbl1(r,1) & tbl1(r,2) & tbl1(r,3) & tbl1(r,4) & tbl(r,5)
Next
For r = 1 to tbl2.Rows.Count
var2(r) = tbl2(r,1) & tbl2(r,2) & tbl2(r,3) & tbl2(r,4) & tbl2(r,5)
Next
r = 0
For each v in Var2
r = r+1
'## Check to see if there is a complete match:
If Not IsError(Application.Match(v, var1, False)) Then
matchRow = Application.Match(v, var1, False)
'## If there is a match, return the value from column K in the first table:
tbl2.Cells(r,11).Value = tbl1.Cells(matchRow,10).Value
Else:
tbl2.Cells(r,11).Value = vbNullString
End If
Next
End Sub