How to move parts of a dynamic pivot table to a separate table? - vba

I have pivot table pulling data from a query from a proprietary database system we use at work. I'm trying to figure out a way to move certain parts of the pivot table to a different sheet where it wouldn't exist as a pivot table there. My problem I'm running into is that the table changes the number of columns and rows depending upon the types and amounts of things that we shipped that shift, so I can't have it simply have my new table equal the cell values in the pivot table.
This is an example of the pivot data having fewer columns and rows based on what occurred that shift at work.
The reason why I would like this in a regular table as opposed to a pivot table is because there's other calculations I'd like to put into the table that extend beyond a pivot table's capabilities (ex. have the user id be displayed as their name, and have a weighted system based off of what the driver moves, but I suppose that's irrelevant.)
I've been poking around the internet, and it seems that the majority of answers to this issue deal with static tables. Any help would be appreciated!

Let's assume you want the cell to have the value from "BEER Total" for "M307577". Then this would be the formula you put in the cell:
=VLOOKUP("M307577",A5:Z100,MATCH("BEER Total",A5:Z5,0),FALSE)
"A5:Z100" would be the whole pivot table and "A5:Z5" would be the first row containing variables.
As you mentioned you are not familiar with VBA, I would suggest this approach:
Use the first column and first row of the second sheet as a reference. Refer to all the variables from the pivot table there (refer to the cell containing IDs and Variables, and pull the formula to the last row for IDs and last column for variables (or a reasonable range as last column and row would not be sufficient)). This will leave you with zeros, empty cells from the pivot table sheet, but will have all the names that you need.
Then refer to those cells and use the aforementioned formula (instead of names, use the cells that you just created).
Whenever the pivot table updates, those cells will be updated as well and you will see the values for the corresponding ID and Variable.

I think you want the GETPIVOTDATA function. Determine what your logic will look like and click on the appropriate combination of cells. Excel will automatically setup the GETPIVOTDATA function appropriately for you.
http://www.contextures.com/xlPivot06.html
Also, if the last used columns and last used rows are changing, you will probably need a Macro to help you with your task.
Sub LastRowInOneColumn()
'Find the last used row in a Column: column A in this example
Dim LastRow As Long
With ActiveSheet
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
End With
MsgBox LastRow
End Sub
Sub LastColumnInOneRow()
'Find the last used column in a Row: row 1 in this example
Dim LastCol As Integer
With ActiveSheet
LastCol = .Cells(1, .Columns.Count).End(xlToLeft).Column
End With
MsgBox LastCol
End Sub
You can use a combination of functions to help you get the last used cell in a specific range.
https://exceljet.net/formula/address-of-last-cell-in-range
From there, I think you can figure out your next steps.
Post back with more information if you still have trouble with this, or start a new post if your question is answered.

Related

Find number of rows in a column of a particular sheet in macros

I am struggling to write a function in VBA which takes sheet name and column as parameters and returns last used row number in that column of that sheet.
I used the following code:
Worksheet("sheetname").Range("e2").End(xlDown).Row
But it returns wrong values... like 104567
Please provide me the code to find row count in a particular column of particular sheet.
The 1 in the code is the column you would like to check. You can change ActiveSheet to any other valid worksheet object.
lLastRow = ActiveSheet.Cells(ActiveSheet.Rows.Count, 1).End(xlUp).Row
An explanation: The number is actually 1,048,576 - the bottom of the worksheet. What it means is that there are no non-empty cells in the column "E:E" below row 2. The solution provided by braX is a standard and a very good way of handling this. In case you want to spec the column by name, you can do this:
Worksheet("sheetname").Range("e" & Worksheet("sheetname").Rows.Count).End(xlUp).Row

Select cell from column with row value

This simple problem has caused me some recent issues. I have a range of cells which are columns that hold onto different types of information. Using a row value (Integer not Range) which is previously determined I am looking to perform a check with the values within a single cell.
For example, I look through a list of names in column A. If the name is found it holds onto the Row value. Let's assume that the row is 10. This row value will be used in checking the column values for this row (I.e. C10, J10, and K10). How can I select a single cell and then compare the values within those cells?
To get the equivalent to MATCH() / INDEX() or VLOOKUP() in VBA for getting the data for Darth Vader here:
we could use something like:
Sub GetTheRowValue()
Dim RowValue As Long
RowValue = Range("A:A").Find(What:="Darth Vader", After:=Range("A1")).Row
MsgBox Range("B" & RowValue).Value
End Sub
The finds the proper row and then acquires data from other columns in that row.

Copying values across a dynamic column and row range

I have the following code that:
copies the column headings (in row 1) from column C across to the second last column
pastes these column headings in row 1 in the column 2 across from the last column with data
pastes the column headings alongside each row of data through to the bottom row
Sub GLDR()
'use End(xlUp) to determine Last Row with Data, in column A of the GLDRYYPP tab
Dim lastRowDR As Long
lastRowDR = Sheets("GLDRYYPP").Range("A" & Rows.Count).End(xlUp).Row
'copy the cost type categories and paste alongside the cost centres
CTNameCol = "S2:AF" & lastRowDR
Sheets("GLDRYYPP").Range("C1", Range("C1").End(xlToRight).Offset(0, -1)).Copy
Sheets("GLDRYYPP").Paste Destination:=Sheets("GLDRYYPP").Range("C1").End(xlToRight).Offset(0, 2)
Sheets("GLDRYYPP").Range(Range("C1").End(xlToRight).Offset(0, 2), Range("C1").End(xlToRight).Offset(0, 2).End(xlToRight)).Copy
Sheets("GLDRYYPP").Paste Destination:=Sheets("GLDRYYPP").Range(CTNameCol)
End Sub
The first two steps have been set to be dynamic for any additional columns added but I am having trouble writing some code that will paste the data through to the bottom row. As you can see the range "S2:AF(last row)" has been written to make use of the result from the lastRowDR dimension.
Is there a way to write the code which will make the copy dynamic across the columns and rows?
Yes there is a way to write the code which will make the copy dynamic across the columns and rows. What you need to do is to identify a distinct quality about the cost centres so that you locate it using something like ActiveSheet.Cells.Find(Txt).
Then you'll be able to determine what CTNameCol should be. There is some helpful info here: Range.Find Method.
If you add add a picture of your spreadsheet I will update this answer with more precise information.

Copy row from one sheet and insert copied row under last row in another sheet

I am in need of your expert assistance.
I am trying to write some code that will copy rows and insert the copied row below the last row in another sheet.
I have a Global sheet that has the data i will be copying. It will need to look in column Q.
I think the problem will be when trying to copy the data, the data in column G is the text name of a Contract Code. But the sheets are name with the Number version.
for example i have a row that has BRREPAIRS in column Q, I need this to copy to Sheet 2870, then i have a row that has BRVOIDS in column Q, I need this to copy to Sheet 2781.
I could have multiple different Contract names so i think i might need to define the text to equal a sheet. So maybe Set BRVOIDS = Sheet.name("2781") Set BRREPAIRS = Sheet.name("2780") and so on until all sheets are defined.
When the data gets copied i need it to find the last row in column a that has data, when it is found it will insert the copied row into the sheet. for example EntireRow.Insert Shift:=xlDown.
I dont have any code at the moment. I would really appreciate all the assistance.
You don't need to do things like Set BRVOIDS = Sheet.name("2781"). In fact, that would be positively harmful since then you would need to run the data in Column Q through a possibly large Select statement to know what variable to use. Instead, you could write a function like
Function TargetSheet(ContractName As String) As Worksheet
'code which uses your secret list to determine target sheet
'Maybe a Select statement, Maybe a Vlookup -- who knows?
Set TargetSheet = 'sheet your code determined
End Function
Sounds like your code will be scanning down column Q, determining where to copy the corresponding row to. Once you get the above function working, you could combine it with something like this:
Function LastRow(TargetCol As Variant, Optional ws As Variant) As Range
'assumes TargetCol is something like 1 or "A"
Dim n As Long
If IsMissing(ws) Then Set ws = ActiveSheet
n = ws.Cells(1, TargetCol).EntireColumn.Rows.Count
Set LastRow = ws.Cells(n, TargetCol).End(xlUp).EntireRow
End Function
This returns as a range the last row containing data (or row 1 if the column is empty) in a specified column in a specified worksheet (which defaults to the Active sheet).
You haven't given enough to go on, but something along the lines of
LastRow("A",TargetSheet(Range("Q" & i).Value)).Insert Shift := xlDown
Might be what you are looking for. Why don't you try to work it out and ask another question (if need be) once you have some actual code?

Sorting Worksheet data by column values using Excel VBA

I have next userform developed in vba, which takes info from a worksheet for displaying info
I want to order all the info aphabetically by a Segment, this is the code:
Function llenarDatosTabla()
Dim vList As Variant
Dim ws As Worksheet: Set ws = Worksheets(BD_PRODXSIST)
ListBox1.Clear
With ws
If (IsEmpty(.Range("AA2").Value) = False) Then
Dim ultimoRenglon As Long: ultimoRenglon = devolverUltimoRenglonDeColumna("A1", BD_PRODXSIST)
vList = ws.Range("AA2:AA" & ultimoRenglon & ":AL2").Value
If IsArray(vList) Then
Me.ListBox1.List = vList
Else
Me.ListBox1.AddItem (vList)
End If
End If
Me.ListBox1.ListIndex = -1
End With
Set vList = Nothing
Set ws = Nothing
End Function
how to make it ordered by 'AD' (SEGMENTO) column???
You can sort your Excel Worksheet in ascending order using VBA statement like the following:
Columns("A:XFD").Sort key1:=Range("AD:AD"), order1:=xlAscending, Header:=xlYes
Note: in the column range Columns("A:XFD") instead of XFD enter the last used column pertinent to your case, e.g. Columns("A:DD").
Hope this will help.
To sort a data table, use Excel Names in conjunction with the CurrentRegion function. This is less risky than hard-coding column references and can be done in two simple steps.
The reason it's preferable to specifying columns is that if you get the columns wrong or they change later, you'll scramble your data! When you perform the sort, the cells in any omitted column(s) will remain where they are, becoming part of the wrong rows. And this is exactly what will happen if you add further columns later, unless you remember to update your VBA.
Here are the two simple steps for using this approach. For this example, I've chosen a data table with four columns and four rows:
We are going to sort by COL3 descending. The cells in the other three columns share identical values, enabling us to readily verify they all stay with the correct rows.
Step 1: choose a cell in the data table that's unlikely to ever be removed, such as the header of a column you intend to make permanent, and define a Name for this cell. You can define the name by selecting the cell and typing directly in Excel's Name dropdown above the worksheet. Here I've used the name RegionTag:
Straight away, CurrentRegion can reference the whole data table just from this. You can see it in action if you code a line of VBA to select the table:
Range("RegionTag").CurrentRegion.Select
This is the result:
That's just for illustration, showing the power of the Name/CurrentRegion combination. We don't need to select the table in order to sort it.
Step 2: define a second Name, this time for the column you want to sort by:
Make sure the Name refers to the entire column, selected by clicking the column header, rather than just a range of cells in the column.
That's it! With these two Names defined, we can sort the data table without concerning ourselves with its rows and columns, even if more are added later:
Range("RegionTag").CurrentRegion.Sort _
key1:=Range("SortCol"), order1:=xlDescending, Header:=xlYes
Here is our data table sorted using the above statement: