vba dynamic sum based on dynamic range values - vba

I would like to thank everyone for their feedback so far it has helped a great deal. one question that I am grappling with is how to make my column values even so I can do a dynamic subtototal.
Column k Column R Column Y Column AF Column AM Column AT
1 2 4 2 3 5
3 9 7 8 2 4
2 3 6 3 5 8
3 3 2
5
TOT 9 14 25 13 12 17
Column k Column R Column Y Column AF Column AM Column AT
1 2 4 2 3 5
3 9 7 8 2 4
2 3 6 3 5 8
3 3 2
5
TOT 9 14 25 13 12 17
on a monthly basis the column values can fluctuate, the question is how do I use VBA to create a dynamic sum based on the column with the most values.
Dim Rin As Range
Dim Rout As Range
Dim lRa As Long
lRa = Range("i" & Rows.count).End(xlUp).Row
Set Rin = ws.Range("i" & lRa)
Set Rout = ws.Range("I" & lRa)
aCell.Range("I11:P12", "R12:AY12").Copy
Rout.Offset(2, 0).Resize(1, 28).Formula = "=SUBTOTAL(9," &
Rin.Address(0, 0) & ")"
lR = ws.Range("I" & Rows.count).End(xlUp).Row - 1 ' Finds the last blank
row
ws.Range("I" & lR).PasteSpecial xlPasteFormats

If you know where your data starts you can use a method such as that given by Shai Rado.
You can't have any entirely empty rows or columns in the range.
You can then feed this lastRow variable into the range address for adding your subtotal formula.
Example: If your data is a continuous set of populated columns starting at Cell D3 the following will get the last used row number in the range of columns:
Option Explicit
Public Sub AddSubTotal()
Dim lastRow As Long
Dim lastCol As Long
Dim firstRow As Long
Dim rowHeight As Long
Dim wb As Workbook
Dim ws As Worksheet
Set wb = ThisWorkbook
Set ws = wb.Worksheets("Sheet2") 'change as appropriate
With ws.Range("D3").CurrentRegion 'change as appropriate
firstRow = .Rows(1).Row
lastRow = .Rows(.Rows.Count).Row
lastCol = .Columns(.Columns.Count).Column
rowHeight = lastRow - firstRow + 1
End With
With ws
.Range(.Cells(lastRow + 1, "D"), .Cells(lastRow + 1, lastCol)).FormulaR1C1 = "=SUBTOTAL(9,R[-" & rowHeight & "]C:R[-1]C)"
End With
End Sub
If you need a different method to find the last used row and last used column there a lots of available resources online including my favourite by Ron De Bruin Find last row, column or last cell. The appropriateness of each method is determined by the shape and properties of your range e.g. no blank columns or rows in range. So choose a method that is right for your data or that can test for different likely cases and apply different methodologies as appropriate.
It is quite difficult to give a definitive answer (and i don't want to code lots of different possible scenarios) to this question without knowing more about the nature and variability of the data. If you familiarise yourself with the methods of finding last row and column you will be able to implement those that suit your needs.

Related

Have Excel Auto Populate Column Headings in Blank Rows (VBA?)

I have a spreadsheet that looks something like this:
A B C D E F
1 Program Year Cycle Date Panel Mtg Rep
2 AAA 2019 1 5/21 ABA Tom
3 AAA 2019 1 5/23 ABB Erin
4
5 BBB 2019 2 6/4 BAB Jim
6
7 CCC 2019 3 7/16 CAB Tom
8 CCC 2019 4 8/27 CBB Kate
9
10
What I'm trying to have it do is, every time a row is skipped, that blank row will automatically be populated with the column headings. So in the example table above, rows 4 and 6 would contain the column headings, while row 9 would remain blank until information was entered on row 10. I've done every possible search I can think of, and haven't found anything that seems applicable. I'm not very familiar with VBA, so I came up with the following series of formulas:
A3) =IF(AND($A2<>"",$A4<>"",$A2<>$A$1),$A$1,"")
B3) =IF(A3=A$1,B$1,"")
C3) =IF(B3=B$1,C$1,"")
D3) =IF(C3=C$1,D$1,"")
E3) =IF(D3=D$1,E$1,"")
F3) =IF(E3=E$1,F$1,"")
These formulas are then extended to the rest of the sheet. This does what I want it to do, but it also fills 8,000+ cells with formulas, including circular references. Which, aside from having to deal with being alerted to the circular references, they also affect other aspects of my sheet, such as conditional formatting, identifying duplicate entries, etc.
As I stated, I'm not really very familiar with VBA, so I don't even know if this is doable using VBA. But if there is some way to achieve the same result without formulas, or at least without circular references, that is what I'm looking for. Thanks so much for any assistance.
This code should work:
see before:
and after:
Sub addHeaders()
Dim ws As Worksheet
Set ws = Sheets("Sheet3")
Dim lastRow As Integer
lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
Dim header As Range
Set header = ws.Range("A1:F1")
For rowNum = 2 To lastRow
If ws.Cells(rowNum, 1) = "" Then
If ws.Cells(rowNum + 1, 1) <> "" Then
ws.Range("A" & rowNum & ":F" & rowNum) = header.Value
End If
End If
Next rowNum
End Sub
Since you said you are new to vba here is quick quick intro to how to run a program:
Something like this is what you're looking for:
Sub tgr()
Dim ws As Worksheet
Dim rHeaders As Range
Dim rDest As Range
Dim ACell As Range
Set ws = ActiveWorkbook.ActiveSheet
Set rHeaders = ws.Range("A1:F1")
For Each ACell In ws.Range("A1", ws.Cells(ws.Rows.Count, "A").End(xlUp)).Cells
If Len(Trim(ACell.Value)) = 0 Then
If Not rDest Is Nothing Then
Set rDest = Union(rDest, ACell)
Else
Set rDest = ACell
End If
End If
Next ACell
If Not rDest Is Nothing Then rHeaders.Copy rDest
End Sub

Copy a range of data from one worksheet & paste 18 times in the other worksheet

Helloo,
I need Copy a range of data from one worksheet & paste 18 times of each data in the other worksheet.
Eg.,
I need to copy the data starting from Row 6 Column A,F,G from one sheet named "Inputs"
And need to paste the data 18 times starting from Row 6 of Column A,C,D in other sheet named "locale_Data"
So, the first data of input sheet should be pasted into Row (6:23) of sheet "locale_Data" & follows the other data in a sequential manner.
Thanks for your help!
If you have values in range say A6:A10 of Inputs worksheet and you would like to copy them in locale_Data worksheet 18 times starting at Row 6 you can do something like this.
Dim LastRow As Long
Dim i, startAt, totalRowsToCopy As Integer
Dim sheet1 As Worksheet
Dim sheet2 As Worksheet
Set sheet1 = ThisWorkbook.Worksheets("Inputs")
Set sheet2 = ThisWorkbook.Worksheets("locale_Data")
LastRow = sheet1.Cells(sheet1.Rows.Count, "A").End(xlUp).Row
sheet1.Range("A6:A" & (LastRow)).Copy
startAt = 6
totalRowsToCopy = LastRow - startAt + 1
For i = 1 To 18
sheet2.Range("A" & startAt & ":A" & (startAt + totalRowsToCopy - 1)).PasteSpecial
startAt = startAt + totalRowsToCopy
Next i
(Edited after Mat's suggestion)
If you just want to copy value in Row 6 18 times in another worksheet you can do something like this:
ThisWorkbook.Worksheets("Inputs").Range("A6").Copy
ThisWorkbook.Worksheets("locale_Data").Range("A6:A23").PasteSpecial
You have to repeat this code for each cells.
And if you want to change 18 to some other number you can always concatenate cell range like
Range("A6:A" & (6 + 18)).PasteSpecial
Let me know if this is not what you are looking for.
you can try something like this. Ihave shown for only one column. you can repeat for other columns. Make sure to change the range $A$1:$A$2 to your desired data range.
D1 = INDEX($A$1:$A$2,QUOTIENT(ROW()-ROW($D$1),18)+1)

Comparing the cell values and printing the count in Excel using a formula or function?

I need a formula or function which is going to fulfill my below mentioned need. I have a excel data of around 11000 rows and data looks somewhat like in Column A:
Now in column B i want the result to be printed like it mentioned below: which literally means it should count the values present in column A and print it in the column B, I don't need to repeat count:
Column A Column B
PC-101 1
PC-101 1
PC-102 2
PC-102 2
PC-103 3
PC-104 4
PC-106 5
PC-107 6
PC-104 4
PC-106 5
PC-106 5
I tried with the "count" series formulas but the result was null.
Even i wrote the macro as given below( which i got from stackoverflow) but even it is printing the repeating count:
Sub CountOccurence()
' Reference: Microsoft Scripting Runtime
Application.ScreenUpdating = False
Set oDict = New Dictionary
Dim wS As Worksheet
Dim r As Integer, rLast As Integer
Set wS = Sheet1
rLast = wS.Cells(1, 1).CurrentRegion.Rows.Count
For r = 3 To rLast Step 1
If Not (oDict.Exists(wS.Cells(r, 1).Value)) Then
oDict.Add wS.Cells(r, 1).Value, 1
Else
oDict.Item(wS.Cells(r, 1).Value) = oDict.Item(wS.Cells(r, 1).Value) + 1
End If
wS.Cells(r, 2).Value = oDict.Item(wS.Cells(r, 1).Value)
Next r
Set oDict = Nothing
Application.ScreenUpdating = True
End Sub
Can anyone help me regarding this? Thanks in advance.
I tried with the "count" series formulas but the result was null.
A simple Excel formula can do this.
Put 1 in Cell B1 and then put this formula in cell B2 and pull it down.
=IF(COUNTIF($A$1:$A2,A2)>1,VLOOKUP(A2,A:B,2,0),B1+1)
Assuming that your data in column a is sorted, you can simply place 1 in B2 this formula in B3 and copy it down:
=IF(A2<>A3,B2+1,B2)
:-)

Inserting blank rows every x number of rows [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Insert row every X rows in excel
I have a large set of data (let's say it goes from B5 to J500 and let's say this range is named rngOutput). I am trying to go through this data and add 2 empty rows every x number of rows where x is a number the user specifies. For example if x is 10 then every 10 rows 2 new rows should be inserted. Conceptually, this is the code that should work:
For i = 1 to Number of rows in rngOutput
If i mod x = 0 Then
Insert 2 Rows
End If
Next i
However, when you insert 2 new rows, the row count changes and the formula messes up (i.e. it adds 2 rows after the first 10 rows, then it adds another 2 rows after the next 8 rows (since it counts those 2 new rows you added as actual rows) then it adds another 2 rows after the next 6 rows, etc.
I am trying to figure out a way to accomplish adding 2 new rows every x number of rows cleanly to avoid the above problem.
Thank you for the help and please let me know if you need additional clarification!
This is like Chris's only fleshed out. When inserting or deleting rows you have to work up from the bottom:
Sub InsertXRowsEveryYRows_WithMeaningfulVariableNames()
Dim NumRowsToInsert As Long
Dim RowIncrement As Long
Dim ws As Excel.Worksheet
Dim LastRow As Long
Dim LastEvenlyDivisibleRow
Dim i As Long
NumRowsToInsert = 2 'any number greater than 0
RowIncrement = 10 'ditto
Set ws = ActiveSheet
With ws
LastRow = .Range("A" & .Rows.Count).End(xlUp).Row
LastEvenlyDivisibleRow = Int(LastRow / RowIncrement) * RowIncrement
If LastEvenlyDivisibleRow = 0 Then
Exit Sub
End If
Application.ScreenUpdating = False
For i = LastEvenlyDivisibleRow To 1 Step -RowIncrement
.Range(i & ":" & i + (NumRowsToInsert - 1)).Insert xlShiftDown
Next i
End With
Application.ScreenUpdating = True
End Sub
Count from the bottom of the range
For i = Number of rows in rngOutput to 1 step -1
If i mod x = 0 Then
Insert 2 Rows
End If
Next i

VBA/Excel - Migration of 'matrix' based dataset to a database

I am trying to migrate a dataset from an old spreadsheet based system to a database. And I have one outstanding single issue to solve.
I have a sheet within a spreadsheet that is acting like a many-to-many table:
It has a column names
It also has a leading column as a rowID/Name making rows unique
On the crossing of rows and columns I have either an empty cell or an
‘X’ (X worked in old system as a relation between two different data
sets)
Rows_name|Column_name1 |Column_name2 |Column_nameX
Row_name1| | X | X
Row_name2| X | |
Row_name3| X | X | X
For each found 'X' I require to copy Row_name and Column_name to separate sheet ready for export.
I.E. For Row_name3 it would be three new rows in a new sheet as Row_name3 has three 'X's
Rows_name|Column_name
Row_name3|Column_name1
Row_name3|Column_name2
Row_name3|Column_name3
In effect I am solving a many to many relation by having a third table.
Therefore I am looking for a help with the algorithm to find all related column/row names for each ‘X’.
For any suggestions how to tackle this I would be very grateful.
Is this what you are trying?
Option Explicit
Sub Sample()
Dim wsInput As Worksheet, wsOutput As Worksheet
Dim LRI As Long, LRO As Long, i As Long, j As Long
'~~> Input Sheet
Set wsInput = Sheets("Sheet1")
LRI = wsInput.Range("A" & wsInput.Rows.Count).End(xlUp).Row
'~~> Output Sheet
Set wsOutput = Sheets("Sheet2")
LRO = 2
For i = 2 To LRI
With wsInput
For j = 1 To 3
If UCase(Trim(.Range("A" & i).Offset(, j).Value)) = "X" Then
.Range("A" & i).Copy wsOutput.Range("A" & LRO)
.Range("A1").Offset(, j).Copy wsOutput.Range("B" & LRO)
LRO = LRO + 1
End If
Next
End With
Next i
End Sub
SNAPSHOT