Excel VBA: Move row to a destination regardless of row count in pivot table - vba

I am new to VBA and have very basic knowledge. I have a pivot table which calculates the count of students grouped by enrollment date and columns consists of Brand Ids
I want to move a row to the end of the pivot table and the number of rows keeps changing. I tried below code but I can use that only when number of rows in pivot table are constant. Can someone please help me to move row to the end of the table though the number of rows are not constant?
ActiveSheet.PivotTables("StudentCount").PivotSelect "'En_Date'['(blank)']", _
xlDataAndLabel + xlFirstRow, True
ActiveSheet.PivotTables("StudentCount").PivotFields("En_Date").PivtoItems( _
"(blank)").Position = 20
'In current sheet I need to move to 20 but actually 20 is not constant
ActiveSheet.PivotTables("StudentCOunt").PivotSelect "En_Date", xlButton, True
I tried below code as well but it is not working:
Dim LS as LONG
LS = ActiveSheet.PivotTable("StudentCount").TableRange2.Rows.Count
ActiveSheet.PivotTables("StudentCount").PivotSelect "'En_Date'['(blank)']", _
xlDataAndLabel + xlFirstRow, True
ActiveSheet.PivotTables("StudentCount").PivotFields("En_Date").PivtoItems( _
"(blank)").Position = "& (LS - 1)"
ActiveSheet.PivotTables("StudentCOunt").PivotSelect "En_Date", xlButton, True
Pivot Table:
Count Of Students
Date A1 A2 A3 A4 Blank Grand TOtal
blank 69 86 23 45 223
01/01/2014 2 25 3 1 31
02/01/2014 1 2 5 8 16
Grand Total 71 112 28 51 262

Hi to answer your question, you do not need VBA to do this.
The reason your pivot is behaving as such is because your Dates are actually not Dates but Dates Entered as Text. See below recreated data:
Re-entering it as actual dates will solve your problem.
So after changing the Text Dates to actual Dates, your pivot sorts your row as you like.
See below:
Hope the solution I presented helps you a bit.
Additional: If however re-entering all the dates is not convenient, try below code:
Dim i As Integer
With ActiveSheet.PivotTables("StudentCount").PivotFields("En Date")
For i = 1 To .PivotItems.Count
If .PivotItems(i) = "(blank)" Then .PivotItems(i).Position = .PivotItems.Count
Next
End With
The code above simply iterates through all the PivotItems, looks for (blanks).
It then change it's position to the last position which is equal to .PivotItems.Count.
Hope this works for you.

Related

Macro to merge two tables in Excel

I’ve had this problem several times and never found a satisfactory way of solving it. I’m sure it must be an easy macro to get this done.
I got a big table with names in the row, months in the columns, and values. Like this example:
Jan-17 Feb-17 Mar-17
CS 12 10 9
GS 1 5 3
JPM 43 35 40
UBS 11 15 13
And every month I get the new values but the issue is: the names are not necessarily the same. There are a few new names and a few old that don’t appear anymore. Let say this as an example:
Apr-17
BNP 21
Citi 75
CS 11
UBS 8
I need to add this to the original big table. So, I need to add a new row full of zeroes for the new stuff of this month and put a zero in this month for the old stuff that disappear. I want something like this as a result:
Jan-17 Feb-17 Mar-17 Apr-17
BNP 0 0 0 21
Citi 0 0 0 75
CS 12 10 9 11
GS 1 5 3 0
JPM 43 35 40 0
UBS 11 15 13 8
The best solution I got until now is loop thought the names in both tables and compare them. When It found a mismatch check the next name in the main table, if those two match that means is a new name. if not, I check the next name in the new table and if that match it means that’s an old name that has stopped appearing. See my code below:
Sub FixColumnsNames()
'This sub Compare the names in the Summary and the Input tab and put the same names on both
Dim LoopRow As Integer
LoopRow = 1
While Sheets("Input").Range("A" & LoopRow) <> "Grand Total"
'Walkthought tha name list until we find the end (Grand Total)
If Sheets("Input").Range("A" & LoopRow).Value <> Sheets("Summary").Range("A" & LoopRow).Value Then
'If two names don't match lets analyse:
If Sheets("Input").Range("A" & LoopRow + 1).Value = Sheets("Summary").Range("A" & LoopRow).Value Then
'New Strategy
Sheets("Summary").Rows(LoopRow).Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
Sheets("Summary").Range("A" & LoopRow).Value = Sheets("Input").Range("A" & LoopRow).Value
End If
If Sheets("Input").Range("A" & LoopRow).Value = Sheets("Summary").Range("A" & LoopRow + 1).Value Then
'Old strategy (it has stopped apearing)
Sheets("Input").Rows(LoopRow).Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
Sheets("Input").Range("A" & LoopRow).Value = Sheets("Summary").Range("A" & LoopRow).Value
End If
End If
LoopRow = LoopRow + 1
Wend
End Sub
This assumes the names are always shorted alphabetically, but this is not a problem for me. This is not a great solution because it fails when there are two old or new names consecutives (among other things).
Can someone please advise how to solve this? Some code or pseudo code would be appreciated. Thanks.
You can solve this much faster with a Vlookup formula. First, find new April values. you can do that with Vlookup April values vs Table values.
Now copy/PasteValue values that are not found (ones with #N/A Vlookup value) below your main table,and use this formula in cell E2(adjust range to your needs) =IFERROR(VLOOKUP(A2,$H$1:$I$10,2,FALSE),0). Drag formula to bottom.

Excel VBA selecting data from a sorted Table

I am running into a problem in VBA in excel.
I am trying to create a participant registration program in excel for a sports tournament. One can add data like the weight, age and name of a participant. And then based on that, The participants are divided into poules named with letters A, B... until Z. I have a table which can sort these poules by letters and then for example only display the participants which are in poule A such as below
Example
Now i want to count the numbers with VBA macros of participants in the poule which is displayed by the sorted table. For example when i sort on poule A it has to return 3 and when i sort on B, it has to return 2.
Determined by the number of participants in a poule the program will print a different poule scheme, depending on the number of participants. (i have this part in VBA)
The problem is when i have a sorted table like below
Example 2
It counts all the participants, and not just the ones in B or any other sorted letter.
I have this:
Sub Count()
Dim nRows As Integer
nRows = Range(Range("A18"), Range("A18").End(xlDown)).Rows.Count
MsgBox (nRows)
End Sub
This works well if you sort A, but when you sort any other letter, it counts All the table until that letter. Eg. when you sort B, it displays 5 (Number of A + B).
I have looked on the internet for a really long time to find a solution but without succes.
I hope my question is clear and that somebody can help me.
I am assuming that you are using worksheet functions. Use Subtotal when working with filtered data.
These parameters evaluate all cells visible or hidden
1 AVERAGE
2 COUNT
3 COUNTA
4 MAX
5 MIN
6 PRODUCT
7 STDEV
8 STDEVP
9 SUM
10 VAR
11 VARP
These parameters evaluate only visible cells
101 AVERAGE
102 COUNT
103 COUNTA
104 MAX
105 MIN
106 PRODUCT
107 STDEV
108 STDEVP
109 SUM
110 VAR
111 VARP
The code does work now, except that it only counts the first letters it encounters.
So when the first column for the poules is for example A A A E A A B B E.
And i sort to A and use the count function, it only returns a value of 3 and not of 5 (because there are 5 A's)
When I sort the table to A, it looks like this (column number, poule value):
14 A
15 A
16 A
18 A
19 A
And it returns just a count of 3, have you maybe got any fixes for that problem as well?
Pictures:
sorted tabel to E
Table
Range.SpecialCells will return a range of only visible cells.
Dim rSource As Range
Dim rVisibleCells
Set rSource = Range(Range("A2"), Range("A2").End(xlDown))
Set rVisibleCells = rSource.SpecialCells(xlCellTypeVisible)
MsgBox rVisibleCells.Rows.Count

Macro VBA code to select a row X row below the one selected

I need your help.
I have a worksheet to update from another one.
Basically is it all the months and the rows are moving from a month to a month because same month LY disappear and same month next year is a rota.
However on this worksheet the format is fixed depending it is 28 or 31 days per month.
so I have a macro asking to enter the row number for Jan :
RowSelected1 = InputBox("Enter row Jan")
Rows(RowSelected1).Select
Range("B" & ActiveCell.Row & ":DJ" & ActiveCell.Row).Select
But instead to do that for every month, I would like from RowSelected1 (January) to count 44 rows and copy this 44th row with the same code as above.
And then count again 44 and copy
etc etc
Do you have anything to help me on that?
Many thanks
M.
Like this?
Rows(RowSelected1 + 44).Select
Range("B" & ActiveCell.Row & ":DJ" & ActiveCell.Row).Select
Dim i As Integer
RowSelected1 = InputBox("Enter row Jan")
Rows(RowSelected1).Select
For i = 1 to 11
Rowselected1 = Rowselected1 + 44
'Do whatever you want to do using Rowselected1 to refer to the row
Next i
Alternatively you can use Offset in a loop over the months:
ActiveCell.Offset(44,0).Select

Compare two sheets and find differences, copy to third sheet

I have been trying to compare two sheets. The sheets are versions, one made in August, the other in September. In Sheet1, column C I have a unique ID that could also be in sheet 2, but could also be not present. On the other hand, I could have NEW ID's in sheet 2, that are not present in Sheet1.
I am trying to:
Identify IDs not in "other" sheet, copy entire row to sheet3
Check if C-column value exists in other sheet, then it has to find
the differences in THOSE two rows, 12 columns out
Example, in sheet1:
ID Jan Feb Mar Apr May
14578596 125 125 125 0 10
22345697 10 10 10 10 20
12563654 150 150 75 75 75
85745896 890 890 890 890 790
and in sheet 2:
ID Jan Feb Mar Apr May
14578596 125 125 125 0 10
12563654 150 150 75 75 75
85745896 890 890 790 890 790
87544545 0 0 0 0 10
In sheet 3, it should copy over the newly added ID 87544545 and all the values in the following columns. It should copy over the ID's 22345697 entire row as well, as being non-existing in the other sheet is considered a difference.
For the others, that exist in both sheets, it should Take "Jan-Jan" and return the difference value. So it should lookup if "ID" exists in other sheet, if it does, compare the Jan-Feb-Mar with each other. Note that ID's are NOT in the same position in the sheets. With ID 85745896 it would return:
ID Jan Feb Mar Apr May
85745896 0 0 100 0 0
I have tried to look at topics such as
Compare data from 2 sheets and find mismatches
and
Check if two rows are the EXACT SAME in MS Excel but can't seem to make them work for my challenge here.
Sub compare()
For i = 1 To last_cell_mainSheet
For j = 1 To last_cell_sheet2
If Worksheets("main_sheet").Range("a" & i).Value = Worksheets("sheet2").Range("a" & j).Value
Then
Worksheets("main_sheet").Range("C" & i).Value = Worksheets("sheet2").Range("b" & j).Value
End If
Next j
Next i
End Sub
The easiest way to solve this is with excel formulas. (if you only want to do it once, or occasionally.) If you need to repeat if often (or have massive amounts of data) use VBA>
You will need to find out about VLOOKUP and IF and ISNA.
Essentially you can add a column to both sheets that looks up the ID in the other sheet and returns Y or N if it is found or not.
You formaula will be something like:
=IF(ISNA(VLOOKUP(MyIDCell,TheTableInTheOtherSheet, 1, false)),"N","Y")
TheTableInTheOtherSheet is a range starting with the ID column (and only neededing one column)
Do the Jan-Jan bit.
Again use a vlookup formula column on sheet1 to get the value of Jan from sheet2. The add a formula to compare them.
You formula will be something like:
=VLOOKUP(MyIDCell,TheTableInTheOtherSheet, 2, false)
TheTableInTheOtherSheet is a range starting with the ID column (and two columns wide)
2 get the second column value
Once you have the data you can sort or filter to reduce the list ot thsoe you need to copy to sheet 3 (best to sort). Then copy and paste them.

Translating results by day to results by week with excel vba

In my excel sheet I have an varying number of dates in column A with associated totals for each date in column B. The dates are somewhat random but I want to find the sum of the associated totals per week. I'm new to vba and I'm having a bit of trouble figuring out how to calculate the totals per week.
The psudo code for what I'm thinking is:
buttonClicked()
Dim sum As Integer, tempDate As Date, current As Date, i As Integer, j As Integer, match As Boolean
sum = 0
tempDate = Range("A1").Value
current = tempDate
For i = 1 To Rows.Count
for j = 0 to 7
tempDate = addDate(d, i, tempDate)
If cell(i,1).Value = tempDate Then sum = sum + cell(i, 2).Value
match = true
Break
End If
Next j
If match = true Then tempDate = current
Else
`next open space in column D is current
current = tempDate
`next open space in column E is sum
sum = 0
Next i
end
Please let me know if there's any better way to solve this problem other than iterating through the entire list and counting 7 days ahead. I should note that A1 is already assumed to be a sunday and I'm not sure how the commented out lines should be implemented. I would be very grateful for any advice at all.
In other column assign the corresponding Year.WeekNumber to each row using the following formula:
=CONCATENATE(YEAR(A1),".",TEXT(WEEKNUM(A1),"00"))
The totals per Year.Week can be obtained using a SUMIF formula or via a PivotTable. The PivotTable can be auto resize if you use a Dynamic Range as DataSource
If you are looking for a series of 7 row sums from column B, then this formula using native worksheet functions should do.
=SUM(INDEX(B:B, (ROW(1:1)-1)*7+1):INDEX(B:B, (ROW(1:1)-1)*7+7))
Fill down to catch successive week periods.
      
If you can supply a starting date (e.g. =MIN(A:A)) and add 7 to it in successive rows, then the weekly starting date could be a reference point for a SUMIFS function. In E9 as,
=SUMIFS(B:B,A:A, ">="&D9,A:A, "<"&D9+7)
Fill down as necessary.
If a VBA solution is necessary, that logic can be brought into a VBA sub or function.