Correlation in Excel Pivot Table - excel

I have a significant amount of data which I must analyse in Excel (this would be much easier in a DB, I realize). Each line item has a T/F indicator for it's membership in a given category and I would like to get a correlation of volume and price for each category across months. The quantity of data I am talking about is between 8-30k records at a time. We use Excel 2010 at my office
Example data:
State | Cat.1 | Cat.2 | Cat.3 | TimeStamp | Volume | Price
WA | TRUE | FALSE | FALSE | 01/31/13 12:00 | 113.1 | 35.64
WA | TRUE | TRUE | FALSE | 01/31/13 13:00 | 65.2 | 32.52
FL | TRUE | FALSE | TRUE | 01/31/13 02:00 | 78.9 | 36.37
FL | TRUE | TRUE | FALSE | 01/31/13 23:00 | 113.9 | 39.39
Ideally what I want is a pivot table that will correlate Volume and Price for a given combination of State, Cat.1, Year, and Month.
Right now I have a Calculated field with formula: =correl(Volume,Price)
However that field returns #DIV/0 for every scenario, but if I double click to view the applicable data, I can manually do the correl() and it works fine.
Any help will be much appreciated!

Not sure if I understand your question entirely but it sounds like you want to correlate based on the value of some of your other columns. I'm assuming therefore if you used autofilter on the header row and you could filter on the states and categories you wanted you could just correlate the visible values. You might need two extra columns with =MONTH( ) and =YEAR( ) with the timestamp.
The UDF i've written below will correlate only visible columns, so go to the VBA editor (Alt F11 ) and copy this, then enter the formular below and filter your columns
=CorrelVisibleCells(F1:F100,G1:G100)
assuming F and G are your volume and price columns
Public Function CorrelVisibleCells(aRange1 As Range, aRange2 As Range)
Dim aCorrelRange1()
Dim aCorrelRange2()
Dim rc As Long
Dim clCount As Long
Application.Volatile True 'This is a volatile function as changing the filter state without changing the cell reference requires a recalc
rc = aRange1.Rows.Count
ReDim aCorrelRange1(rc) 'Largest they could be, will crop at the end
ReDim aCorrelRange2(rc)
clCount = 0
For i = 1 To rc
If Not aRange1.Cells(i).EntireRow.Hidden Then ' Can't use SpecialCells(xlCellTypeVisible) in a UDF
aCorrelRange1(clCount) = aRange1.Cells(i).Value
aCorrelRange2(clCount) = aRange2.Cells(i).Value
clCount = clCount + 1
End If
Next
ReDim Preserve aCorrelRange1(clCount - 1)
ReDim Preserve aCorrelRange2(clCount - 1)
CorrelVisibleCells = WorksheetFunction.Correl(aCorrelRange1, aCorrelRange2) 'Get Excel to do the correlation on our new arrays
End Function

Related

auto increment rows that belong to the same group of values

in a column, i have some values like this:
|------------|----------------|
| false | abc |
| | def |
| false | mpla |
| | xyz |
|-----------------------------|
and i need to have all rows from each false row, till the next false value,
in a group, which will auto increment:
|------------|----------------|
| 1 | abc |
| 1 | def |
| 2 | mpla |
| 2 | xyz |
|-----------------------------|
which excel formula shoul i try with?
Just something to note, without any helper row: =COUNTIF(INDIRECT("A1:A"&ROW(A1));FALSE). Thought I would put it out there :)
Obviously if your column a contains pure text it becomes: =COUNTIF(INDIRECT("A1:A"&ROW(A1));"FALSE")
Add an extra row before your data (row 1) and then put the formula =C1+IF(A2="false";1;0) in the third (C) column.
As Dmitry noted, you can add an additional row at the top and use it to initialize an accumulator at zero. Each time you run into a non-blank cell, you can increment the previous value by 1.
The reason I didn't check for false, is because false is a bit tricky. If you used TRUE instead of FALSE, your formula for row 2 (onward) would be:
=$C1+IF($A2=TRUE,1,0)
I do not have access to Excel at this time, to write a VB script, but I wrote a simple Google script to populate IDs. I am sure you can do something very similar in VB.
Sample Data
Group Name ID <-- Add third column
FALSE abc
def
FALSE mpla
xyz
You can execute the script to run through the sheet and fill in the ID column.
function autoAassignGroupId() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(),
rangeData = sheet.getDataRange(),
lastColumn = rangeData.getLastColumn(),
lastRow = rangeData.getLastRow(),
searchRange = sheet.getRange(2, 1, lastRow-1, lastColumn-1),
rangeValues = searchRange.getValues(),
auto_index = 0;
for (row = 0 ; row < lastRow - 1; row++) {
if (rangeValues[row][0] === false) auto_index++;
sheet.getRange(row + 2, lastColumn).setValue(auto_index);
}
}

VBA for Excel to insert rows based on text in sequential rows

I receive an Excel report showing number of patients in a center based on the payer type. Column A lists the center name and the payer types. If there are no patients for a particular payer type, that payer is not listed in the list. I would like to run a script to insert a row as a placeholder wherever a payer is not listed. For example, this is the output of the report:
A | B | C
| |
Region A | Date1 | Date2
| |
Center 123 | |
| |
Private | 4 | 6
Medicaid | 60 | 58
Total | 64 | 64
| |
Center 456 | |
| |
Private | 4 | 4
Medicare | 6 | 8
Hospice | 2 | 2
Managed Cr | 8 | 10
Total | 20 | 24
But I need for all payers/total lines to be listed for each center:
Center 123
Private
Medicare
Medicaid
Medicaid Pnd
Veterans
Hospice
Assisted Lv
Managed Cr
Unassigned
Total
Bed Hold
Total with Bed Holds
Can this be done with VBA to, for example, insert a row after "Private" if "Medicare" is not in the next row - and then put "Medicare" in that new row (column A)? Then insert a row after "Medicare" if "Medicaid" is not in the next row - and put "Medicaid" in the new row, and so on down the list. Thank you in advance for any help you can offer.
Quick question. Your title is vbscript, but your tag is excel-vba. No sure if you know they are two different things.
If your looking for a vba solution, also referred to as a macro, here's an idea.
If you are doing this for esthetics, turn the used range into a table, and hide the rows that don't have any values. This can be done without a macro. But here's a quick macro example:
Sub Button1_Click()
Dim objTable As ListObject
Worksheets("Sheet1").Activate
ActiveSheet.UsedRange.Select
Set objTable = ActiveSheet.ListObjects.Add(xlSrcRange, Selection, , xlYes)
ActiveSheet.ListObjects("Table1").Range.AutoFilter Field:=2, Criteria1:= _
"<>"
End Sub
If you were looking for a vbscript solution, its similar, but different syntax.
And a note, you can "Record Macros" in excel. This will allow you to perform a task manually, and excel will give you the macro version of the action. It's not perfect, but for stuff like this it will give you a good place to start.
Yes, this can easily be done with VBA. These are the logical steps you need to take:
Go through each row;
for each row;
Check text in column A and text in the cell below;
if no action is required, do nothing and go to the next row;
if an action is required, execute the desired action;
You can update your question with the code you have so far and describe in detail where exactly you are stuck, and I am pretty sure that we will be able to help you. Please google a specific question first before you ask it here.

AutoIncrement ID Number (Works with Sorting)

Good Morning,
I'm constructing a table and I'd like to assign each entry a unique ID number that autoincrements as new values are entered into the table. Here's a sample table to give a visual:
+----+------------+-----------+
| ID | First Name | Last Name |
+----+------------+-----------+
| 1 | John | Smith |
| 2 | Steve | Wozniak |
| 3 | Steve | Jobs |
+----+------------+-----------+
In the above table, if I enter a 4th person, what I would like to happen is that the ID is automatically generated (in this case as 4). I've tried an in cell formula such as:
=Row([#ID])-1
This works until you sort the table, in which case the ID numbers get all scrambled up. I'd like to calculate what the row number should be, but then keep that value constant. Any ideas?
If you want a static increment key, you should use a code like this in your output worksheet
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Column = 2 Then
Target.Offset(0, -1).Value = Target.Row - 1
End If
End Sub
If you just want a unique key that isn't actually incrementing based on previous one, you can use a formula like =SUM(CODE(MID(B2&C2,ROW(INDIRECT("1:"&LEN(B2&C2))),1))) in your A2 cell (closing with CSE) and pull down. However, if you extend a formula too much it will affect your sheet's performance.

Get a random row in a sheet, where column is a known value

I have an Excel file that contains data like this:
id line | idsector |sector | isSectorPrior |etc...
1 | 1 | east | no
2 | 1 | east | no
3 | 1 | east | yes
4 | 1 | east | yes
5 | 2 | west | yes
6 | 2 | west | yes
7 | 2 | west | no
8 | 2 | west | yes
I need to draw one line where isSectorPrior will be "yes", and then, when I have the row, get id line that is in the cell 1.
So here, it can choose row 3, 4, 5, 6, or 8.
I found a lot or samples, that uses the range (an example), but they can return e.g. row number 7, even though it has a "no". This should not happen.
How can I specify, get a random row, but only where iSectorPrio is yes?
My current code, not so much because I didn't find anything that could match what I want :
'get a sheet to use and find a random row
Set tempSheet = ActiveWorkbook.Sheets(1).Select
'loop 50 times, to draw 50 different lines
For i = 1 To 50
'todo : get randow row, where IsSelectPrio is yes
'then do whatever I want with it, like write copy it in another sheet or a csv
Next i
The difficulty here (for me) is, there is no particular range, all I found were using the range. And considering, thats in the first rows, it it not part of the table.
Is there a way to do what I want?
There are at least two approaches.
Approach 1: Get a random row number (e.g. using the code from that other solution you link to), then check if you have a "yes" on that row. If not, then get a new random number; repeat until you get a yes. (Warning: this will go into an infinite loop if you have no yes'es.)
Approach 2: Start by making a list of row numbers that have a yes; then pick a random one among those.
If your only problem is finding the right range to pick a random row you can do this:
(If your worksheet has to look the same way it looks now, make a copy of it)
Dim ws As Worksheet
Dim sortRangeRows As Integer
Dim lastRow, lastColumn As Integer
'Get sortRange
lastRow = ThisWorkbook.Sheets(1).UsedRange.SpecialCells(xlCellTypeLastCell).Row
lastColumn = ThisWorkbook.Sheets(1).UsedRange.SpecialCells(xlCellTypeLastCell).Column
Set ws = ThisWorkbook.Sheets(1)
Set sortRangeRows = ws.Range(ws.Cells(1, 1), ws1.Cells(lastRow, lastColumn))
'Sort after isSectorPrior:
sortRangeRows.Sort Key1:=sortRangeRows(1, 4), Order1:=xlAscending, Header:=xlYes, Orientation:=xlSortColumns
'Find the last row with a "yes" in it (not entirely sure about this piece of code)
lastRowYes = ws1.Cells.Find("yes", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
Now you have your range of rows with a yes.
HTH

How do iterate through a number of rows and call vba depending on which line is flagged

I have a table that retrieves a list of available reports to the user. The user then enters an 'X' in a specific column next to the report they wish to generate.
How do I iterate through each available row and work out if the user has entered 'X'?
A | B | C | D
001 | REPORT A | fnReportA | X
002 | REPORT B | fnReportB | <NULL>
003 | REPORT C | fnReportC | <NULL>
OR
How do I iterate through each row when the list is retrieved and put a BUTTON at the end of each row that links to the vba to generate the report?
For Each will do the type of search you are looking to do
A quick example:
Option Explicit
Sub testit()
Dim c As Range
For Each c In Range("D2:D10").Cells
If c.Value = "X" Then
Debug.Print c.Row
End If
Next
End Sub
This will print the row number of each cell that has an X.

Resources