I'm looking for a way for copying down all data found between a range and paste it in a next column.
A= text data
B= Random numbers but always starting from 1
C= some data
D= My needed solution
Example:
A B C D
018404.00 1 20 20
018404x0 2 0 20
018404f1 2 0 20
018404v1 3 0 20
11000-0532 4 0 20
1004-1101 5 0 20
0720-0125 3 0 20
0810-0001 3 0 20
0710-0040 3 0 20
052269.00 1 0 80
052269v6 2 0 80
11001-0000 3 0 80
1001-1110 4 0 80
0720-0500 2 0 80
0810-0001 2 80 80
0720-0002 2 0 80
052275.00 1 0 160
052275v2 2 160 160
When the value in column B is 1 then find value in column C (in Range B:B from 1 to 1) copying it to D
I have tried it with a formula but this limits the depth. If value on Column C isto far from the 1 row it doesn't work.
=IF(AND(B2=1;C2=0);IF(B3=1;0;IF(C3=0;IF(C4=0;C5;C4);C3));IF(C2>0;C2;I1))
So I think I need a vba solution.
i think you need something like this.
This code search max value between your 1 and 1 value
Sub FindValBetweenOne()
Dim LastRow As Long
Dim FindVal As Long
LastRow = Cells.Find("*", searchorder:=xlByRows, searchdirection:=xlPrevious).Row
For I = 1 To LastRow
If Cells(I, "B").Value = 1 Then 'find next "1"
FindVal = Cells(I, "C").Value
J = I + 1
Do While (J <= LastRow And Cells(J, "B").Value <> 1)
If Cells(J, "C").Value > FindVal Then
FindVal = Cells(J, "C")
End If
J = J + 1
Loop
End If
Cells(I, "D").Value = FindVal
Next I
End Sub
Related
I have attached the input file format with sample data here.
Can someone help with the macro code to get the output data as mentioned below.
Input file for Macro :
Roll No Name Mark1 Mark2
1 Abc 10 35
20 25
30 40
2 def 20 10
15 5
25 2
30 3
The merged cells data needs to be obtained in separate rows along with marks data.
Output Data to be obtained :
Roll No Name Mark1 Mark2
1 Abc 10 35
1 Abc 20 25
1 Abc 30 40
2 def 20 10
2 def 15 5
2 def 25 2
2 def 30 3
Check this out,
Sub unMerge()
Dim i As Long, strA As String, strB As String
Range("A:B").unMerge
strA = Cells(2, 1)
strB = Cells(2, 2)
For i = 2 To Cells(Rows.Count, 4).End(xlUp).Row
If Cells(i, 1) = "" Then
Cells(i, 1) = strA
Cells(i, 2) = strB
Else
strA = Cells(i, 1)
strB = Cells(i, 2)
End If
Next i
End Sub
Easier to fill the blanks with a formula:
Dim r As Range
Set r = Range("A1").CurrentRegion
r.UnMerge
r.SpecialCells(xlCellTypeBlanks).FormulaR1C1 = "=R[-1]C"
In Excel I have a the following set up in Sheet 1
A B C D E
1 a 12 123
2 b 234 2342
3 c 12 23 54 342
4 d 234 33 54
5 e 234 34 66
6 f 345
and the table below in Sheet 2
A B
1 b 2
2 d 3
3 e 1
Sheet 2 determines if some extra rows should be added to Sheet 1 or not, and if not, the row should be deleted.
Giving the result below in Sheet 1
A B C D
1 b 234 2342
2
3
4 d 234 33 54
5
6
7
8 e 234 34 66
9
Note that b,d & e were the only rows remaining from the original data and also the number of rows added below that row relate to the number in column B in sheet 2 for each remaining row.
I would like to use VBA to carry this out. I have read that deleting rows based on criteria means you need to go through a loop from the bottom row to the top row, but I am struggling to make it work for my example.
Here is the code I have used so far but it doesn't seem to work:
Sub maketab()
Range("A1").Select
Dim r As Long
lr = Range("A1").Row
hr = Range("A1").Offset(8 - 1).Row
For r = hr To lr Step -1
Dim given_rng As Range
Set given_rng = Sheet2.Range("A1")
Dim p As Long
lr_small = given_rng.Row
hr_small = given_rng.End(xlDown).Row
For p = hr_small To lr_small Step -1
If Range("A" & r).Value = Range("A" & p).Value Then
'Add a row below
Range("A" & r).Offset(1).Select
Selection.Resize(Sheet2.Range("A" & p).Offset(0, 1).Value).EntireRow.Insert
Range("A" & r).Select
Else
'Delete a row
Rows(r & ":" & r).Select
Selection.Delete Shift:=xlUp
End If
Next p
Next r
End Sub
As always any help would be greatly appreciated
Try this:
Sub test()
Dim xlws1 As Worksheet
Dim xlws2 As Worksheet
Dim xlws3 As Worksheet
Dim i As Integer
Dim j As Integer
Dim k As Integer
'setting sheet variables
Set xlws1 = Worksheets("Sheet1")
Set xlws2 = Worksheets("Sheet2")
Set xlws3 = Worksheets("Sheet3")
k = 1 'setting initial value of k
i = 1 'setting initial value of i
Do While IsEmpty(xlws1.Range("A" & i)) = False
j = 1 'resetting j
Do While IsEmpty(xlws2.Range("A" & j)) = False 'setting loop up
If xlws1.Range("A" & i).Value = xlws2.Range("A" & j).Value Then 'if value matches current sheet 1 value
xlws1.Rows(i).Copy ' copy row
xlws3.Range("A" & k).PasteSpecial xlPasteAll 'paste row
k = k + 1 'increment k
Exit Do ' move on
End If
j = j + 1 'increment j
Loop
i = i + 1 'increment i
Loop
End Sub
I having a problem on the code below.
On row 130 i need to insert blank rows equal to the value in J.
The code now is inserting blank rows equal to J but is starting on row J. I need to start on row k and then insert blank rows of J. How do I define the starting row and the number of blank rows?
70 j = ws1.Cells(ws1.Rows.Count, "E").End(xlUp).Row
80 k = 2
90 x = 1
100 Do While x < j
110 With ws2
120 If j > 0 Then
'Insert J number of rows starting on row = k
130 .Rows(j).Resize(LastRow).Insert
140 For i = 2 To rngtocopy.Rows.Count
150 With ws2.Range("K" & k)
160 .Offset(0, 0).Value = rngtocopy(i, 1)
170 .Offset(0, 1).Value = rngtocopy(i, 2)
180 End With
190 k = k + 1
200 Next i
210 End If
220 End With
230 x = x + 1
240 Loop
I don't know if I understand your question correctly, but try this:
Set ws1 = Sheets("Calc")
Set ws2 = Sheets("Dealer Orders")
LastRow = ws1.Cells(ws1.Rows.Count, "E").End(xlUp).Row
Set rngtocopy = ws1.Range("E2", ws1.Cells(LastRow, "F"))
For i = 1 To rngtocopy.Rows.Count
With ws2.Range("K2")
.Resize(, 2).Insert xlDown
.Offset(-1, 0).Value = rngtocopy(i, 1)
.Offset(-1, 1).Value = rngtocopy(i, 2)
End With
Next
Is this somehow what you're trying? HTH.
I think what I'm trying to do is pretty basic, but I'm brand new to VBA so I'm getting stuck and the answers I've found are close, but not quite right.
I have a list of row entries, like this:
1 4 32 2 4
2 6 33 1 3
1 4 32 2 4
4 2 30 1 5
Notice that rows 1 and 3 are duplicates. I'd like to only have a single instance of each unique row but I don't want to just delete the duplicates, I want to report how many of each type there are. Each row represents an inventory item, so deleting duplicate entries without indicating total quantity would be very bad!
So, my desired output would look something like this, where the additional 6th column counts the total number of instances of each item:
1 4 32 2 4 2
2 6 33 1 3 1
4 2 30 1 5 1
My data sets are larger than just these 5 columns, they're closer to 10 or so, so I'd like to put that last column at the end, rather than to hardcode it to the 6th column (i.e., column "F")
Update:
I found some code that worked with minor tweaking, and it worked this morning, but after messing around with some other macros, when I came back to this one it was telling me that I have a "compile error, wrong number of arguments or invalid property assignment" and it seemed to be unhappy with the "range". Why would working code stop working?
Sub mcrCombineAndScrubDups2()
For Each a In range("A1", Cells(Rows.Count, "A").End(xlUp))
For r = 1 To Cells(Rows.Count, "A").End(xlUp).Row - a.Row
If a = a.Offset(r, 0) And a.Offset(0, 1) = a.Offset(r, 1) And a.Offset(0, 2) = a.Offset(r, 2) Then
a.Offset(0, 4) = a.Offset(0, 4) + a.Offset(r, 4)
a.Offset(r, 0).EntireRow.Delete
r = r - 1
End If
Next r
Next a
End Sub
Assuming that your data starts from A1 on a worksheet named ws1, the following code removes the duplicated rows. Not by shifting the whole table but deleting the entire row.
Sub deletedupe()
Dim i As Integer
Dim j As Integer
Dim k As Integer
Dim row1 As String
Dim row2 As String
i = 1
j = 1
k = 1
Do While Sheets("ws1").Cells(i, 1).Value <> ""
row1 = ""
j = 1
Do While Sheets("ws1").Cells(i, j).Value <> ""
row1 = row1 & Sheets("ws1").Cells(i, j).Value & " "
j = j + 1
Loop
k = i + 1
Do While Sheets("ws1").Cells(k, 1).Value <> ""
row2 = ""
j = 1
Do While Sheets("ws1").Cells(k, j).Value <> ""
row2 = row2 & Sheets("ws1").Cells(k, j).Value & " "
j = j + 1
Loop
If row1 = row2 Then
Sheets("ws1").Rows(k).EntireRow.Delete
Else
k = k + 1
End If
Loop
i = i + 1
Loop
End Sub
I have a workbook that has thousands of defined name regions located in various worksheets. I'm trying to extract them all and line them up in another workbook.
Most of the defined name regions are 1 row tall (and hundreds of cols wide)... but a few are 3-4 rows tall.
So for example,
Name1
10 5 10 12 30 10 12 10 5 10 12 30 10 12 ...
Name2
10 11 10 12 30 10 12 10 11 10 12 30 10 12 ...
10 11 10 12 30 10 12 10 11 10 12 30 10 12 ...
10 11 10 12 30 10 12 10 11 10 12 30 10 12 ...
For instances where the region is more than one row tall, I'd like to collapse it to a single row by taking the SUM of the entire column.
So Name2 would be copied to the new workbook as the following:
30 33 30 36 90 30 36 30 33 30 36 90 30 36
I have some VBA/VBS written that works perfectly (and fast!) for cases where the region is 1 row tall, but I'm not sure how to handle summing the taller regions in an efficient way.
What's the best way to fill in the question marks below?
My code so far hasn't had to explicitly loop through the cells of a region; I'm hoping that that won't be the case here either. Any advice appreciated!
Dim irow
irow = 0
Dim colsum
'rem Loop through all names and copy over the valid ones
For Each nm in wbSource.Names
'rem Dont copy any name that isnt visible
If nm.Visible = True Then
'rem Only copy valid references that start with "ByWeek"
If InStr(1, nm.RefersTo, "#REF") = 0 And InStr(1, nm.Name, "ByWeek") > 0 Then
'rem Only copy if the range is one row tall
If nm.RefersToRange.Row.Count = 1 Then
wsDest.Range("A3").Offset(irow, 0).Value = nm.Name
wsDest.Range("A3",wsDest.Cells(3,nm.RefersToRange.Columns.Count+1)).Offset(irow, 1).Value = nm.RefersToRange.Value
irow = irow + 1
' rem If the named region is several rows tall, then squish it into one row by taking SUM of each column
elseif nm.RefersToRange.Row.Count > 1 Then
wsDest.Range("A3").Offset(irow, 0).Value = nm.Name
???????????????????????????????????
irow = irow + 1
End If
End If
End if
Next
You can update your code such that it adds all the cells in the given range (nm.RefersToRange), independently upon the number of cells:
Dim irow
irow = 0
'rem Loop through all names and copy over the valid ones
For Each nm in wbSource.Names
'rem Dont copy any name that isnt visible
If nm.Visible = True Then
'rem Only copy valid references that start with "ByWeek"
If InStr(1, nm.RefersTo, "#REF") = 0 And InStr(1, nm.Name, "ByWeek") > 0 Then
If nm.RefersToRange.Rows.Count >= 1 Then
wsDest.Range("A3").Offset(irow, 0).Value = nm.Name
Dim totVal As Long: totVal = 0 'I assumed that target values are Long; update this to the proper type is required
For Each cell In nm.RefersToRange.Cells
If (IsNumeric(cell.Value)) Then totVal = totVal + cell.Value
Next
wsDest.Range("A3", wsDest.Cells(3, nm.RefersToRange.Columns.Count + 1)).Offset(irow, 1).Value = totVal
irow = irow + 1
End If
End If
End if
Next
there is no best way as everyone might think their way is the best.
I would suggest using arrays instead of working with the range objects directly as arrays would have been much faster.
Consider
Now running the code
Option Explicit
Sub Main()
Dim lastRow As Long
Dim lastCol As Long
lastRow = Range("A" & Rows.Count).End(xlUp).Row
lastCol = Cells(1, Columns.Count).End(xlToLeft).Column
Dim arr As Variant
arr = Range(Cells(1, 1), Cells(lastRow, lastCol))
ReDim sumArr(UBound(arr, 2)) As Variant
Dim i As Long
Dim j As Long
Dim colSum As Long
For i = LBound(arr, 1) To UBound(arr, 2)
For j = LBound(arr, 1) To UBound(arr, 1)
colSum = colSum + arr(j, i)
Next j
sumArr(i) = colSum
colSum = 0
Next i
ReDim finalArray(UBound(sumArr) - 1) As Variant
For i = 1 To UBound(sumArr)
finalArray(i - 1) = sumArr(i)
Next i
Range("A10").Resize(1, UBound(finalArray, 1) + 1) = finalArray
End Sub
Results in
The idea to use arrays is taken from here
And all you need to do is modify the range you want to reprint the array to
Range("A10").Resize(1, UBound(finalArray, 1) + 1) = finalArray
So if you use the above code I think all you'll need to change will be
wsDest.Range("A3").Resize(1, UBound(finalArray, 1) + 1) = finalArray
Here's the code I ended using: It loops through each column for the defined named range. It isn't fast, but it works well enough, as 90% of my ranges are just one row tall.
I've just inserted this code where where it says ????...???? in my question above, :
For j = 1 To nm.RefersToRange.Columns.Count
colsum = 0
For i = 1 To nm.RefersToRange.Rows.Count
If IsNumeric(nm.RefersToRange.Cells(i, j).Value) Then
colsum = colsum + nm.RefersToRange.Cells(i, j).Value
End If
Next
wsDest.Range("A3").Offset(irow, j).Value = colsum
Next