Increment difference between cells - excel

I'm trying to duplicate data in a sheet with increments of 12 between each cell from a sheet with 1 cell per row. Between the 12-incremented rows there's other data. This means I can't drag to extend the formula. Like this for customer numbers:
'SheetA'E3 = 'SheetB'Y2
'SheetA'E15 = 'SheetB'Y3
'SheetA'E27 = 'SheetB'Y4
..and so on. I've tried extending 12/24 cells at a time and copying but I can't make it work. Extending doesn't add +1 to one sheet, just +12/+24 to both. Doing this manually will take months. Can this be done without a VBA solution?
Any suggestions? I'm sorry if my terminology isn't on point here.
SheetA:

Try this (run as VBA code):
Sub test1()
For i01 = 0 To 100
Worksheets("SheetA").Cells(3 + 12 * i01, 5) = Worksheets("SheetB").Cells(2 + i01, 25)
Next i01
End Sub

Power Query, available in Windows Excel 2010+ and Office 365, can produce your SheetA given SheetB. Not sure about the effect of the variability you mention.
The query assumes that the correct parameters are listed as column headers in Sheet B. The column headers will get copied over as parameters to sheet A.
To use Power Query:
Select some cell in your Data Table
Data => Get&Transform => from Table/Range
When the PQ Editor opens: Home => Advanced Editor
Make note of the Table Name in Line 2
Paste the M Code below in place of what you see
Change the Table name in line 2 back to what was generated originally.
Read the comments and explore the Applied Steps to understand the algorithm
M Code
let
//Read in the data
//Change table name in next line to be the "real" table name
Source = Excel.CurrentWorkbook(){[Name="Table12"]}[Content],
//set data types based on first entry in the column
//will be independent of the column names
typeIt = Table.TransformColumnTypes(Source,
List.Transform(
Table.ColumnNames(Source), each
{_,Value.Type(Table.Column(Source,_){0})})
),
//UNpivot except for the c.number and c.name columns to create the Parameter and Level columns
#"Unpivoted Other Columns" = Table.UnpivotOtherColumns(typeIt, {"C. number", "C. name"}, "Parameter", "Level"),
//Group By C.Number
//Add the appropriate rows for each customer
//And a blank row to separate the customers
#"Grouped Rows" = Table.Group(#"Unpivoted Other Columns", {"C. number"}, {
{"All", each _, type table [C. number=nullable number, C. name=nullable text, Parameter=text, Level=any]},
{"custLabel", (t)=> Table.InsertRows(t,0,{
[C. number = null, C. name=null,Parameter = null, Level = null],
[C. number = null, C. name=null, Parameter = "Customer Number", Level="Customer Name"],
[C. number = null, C. name=null,Parameter = t[C. number]{0}, Level = t[C. name]{0}],
[C. number = null, C. name=null,Parameter = "Parameter", Level = "Level"]
})}
}),
//Remove the unneeded columns and expand the remaining table
#"Removed Columns" = Table.RemoveColumns(#"Grouped Rows",{"C. number", "All"}),
#"Expanded custLabel" = Table.ExpandTableColumn(#"Removed Columns", "custLabel", {"Parameter", "Level"}, {"Parameter", "Level"}),
//Remove the top blank row
//promote the new blank row to the Header location
#"Removed Top Rows" = Table.Skip(#"Expanded custLabel",1),
#"Promoted Headers" = Table.PromoteHeaders(#"Removed Top Rows", [PromoteAllScalars=true]),
//data type set to text since it will look better on the report
#"Changed Type" = Table.TransformColumnTypes(#"Promoted Headers",{{"Customer Number", type text}, {"Customer Name", type text}})
in
#"Changed Type"```
Data
Results

[ Indirect with row() ]
Assuming 'SheetA'E3 column is the target and 'SheetB'Y2 is the source data.
In SheetA!E3 cell put:
=INDIRECT("SheetB!Y"&( ( (row()-3) / 12) + 2)
Press Enter
Then select SheetA!E3 cell, copy. Then paste in SheetA!E24. The formula will update itself.
Idea :
Find the relation between the target cell row number and the source cell row number. [ b > a : 3 > 2 , 15 > 3, 27 > 4 ] leads to a = (b-3)/12 + 2 . (The math is sort of like figuring out a straight line equation from 3 coordinate.) Then use INDIRECT() to combine the calculated row number with the column address.

Related

Excel merge two tables, repeating 2nd table lookup row

I have two Excel Tables with a 'lookup' column to merge against. I want to merge to a new table with all the lookup values expanded. If I were doing this in python or some such, the pseudo-code would be something like:
for unique day in Tbl1
row1 = day
row2 = ""
for event in Tbl1 day
v = event's lookup value in Tbl2
row1 += event + (len(v) - 1) blank columns
row2 += v
print(row1)
print(row2)
I'd like to avoid VBA, but would like to use new dynamic array functions (preferred) or power query (if necessary), but I can't figure out how to get the repeat to happen. The power query merges I've tried aren't complete.
The original data (where I've used abbreviations for my real data), has a number of events per day. The 'lookup' column shows the different levels of that event for that day.
Tbl1
day
event
lookup
1
Re
eoni2
1
Gr
eoni1
1
We
eoni1
2
Tn
eoneonii2
2
Ga
eon1
2
Gr
eoni1
Tbl2
lookup
c1
c2
c3
c4
c5
c6
c7
c8
eeononii
E
E
O
N
O
N
I
I
eon1
E
O
N
eoneonii2
E
O
N
E
O
N
I
I
eoni1
E
O
N
I
eoni2
E
E
O
O
N
N
I
I
Tbl1
Data will change: number of events per day, event value, what lookup value might be for an event.
The 'event' may or may not repeat from one day to the next, but will be unique within a day.
Order (top to bottom) should be maintained in resulting merge (left to right).
Max number of days = 3.
Tbl2
generally static and top to bottom order can be changed if needed.
may contain entries that are not used by Tbl1.
min of 3 and max of 8 values per row.
Tbl3 output
ideally, the 'event' name would not repeat, as shown below, but can if it keeps formula cleaner.
the number of columns for each day in output Tbl3 may not be the same, as shown, e.g. day 1 rows have 16 and day 2 rows have 15 here.
The output I want:
Tbl3
day
e1
e2
e3
e4
e5
e6
e7
e8
e9
e10
e11
e12
e13
e14
e15
e16
1
Re
Gr
We
E
E
O
O
N
N
I
I
E
O
N
I
E
O
N
I
2
Tn
Ga
Gr
E
O
N
E
O
N
I
I
E
O
N
E
O
N
I
Thanks much.
This can be accomplished using Power Query, available in Windows Excel 2010+ and Excel 365 (Windows or Mac)
To use Power Query
Select some cell in your Data Table
Data => Get&Transform => from Table/Range or from within sheet
When the PQ Editor opens: Home => Advanced Editor
Make note of the Table Name in Line 2
Paste the M Code below in place of what you see
Change the Table name in line 2 back to what was generated originally.
Read the comments and explore the Applied Steps to understand the algorithm
M Code
let
//Read in both tables
//Edit Source and Source1 lines to reflect your actual table names
Source = Excel.CurrentWorkbook(){[Name="Tbl_1"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,{{"day", Int64.Type}, {"event", type text}, {"lookup", type text}}),
Source1 = Excel.CurrentWorkbook(){[Name="Tbl_2"]}[Content],
#"Changed Type1" = Table.TransformColumnTypes(Source1,
List.Transform(Table.ColumnNames(Source1), each {_, type text})),
//Join the two tables based on the lookup column
//then remove that column
#"Join Tables" = Table.NestedJoin(#"Changed Type","lookup", #"Changed Type1","lookup", "joined"),
#"Removed Columns" = Table.RemoveColumns(#"Join Tables",{"lookup"}),
//Add index column to maintain original Event order
#"Added Index" = Table.AddIndexColumn(#"Removed Columns", "Index", 0, 1, Int64.Type),
//Expand the joined table and remove the Index column
#"Expanded joined" = Table.ExpandTableColumn(#"Added Index", "joined", {"c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8"}, {"c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8"}),
#"Removed Columns2" = Table.RemoveColumns(#"Expanded joined",{"Index"}),
//Unpivot all the "value" columns
//Then remove the "Attribute" column (the previous column Headers)
#"Unpivoted Other Columns" = Table.UnpivotOtherColumns(#"Removed Columns2", {"day", "event"}, "Attribute", "Value"),
#"Removed Columns1" = Table.RemoveColumns(#"Unpivoted Other Columns",{"Attribute"}),
//Group by "day"
#"Grouped Rows" = Table.Group(#"Removed Columns1", {"day"}, {
{"event & value", (t)=> let
remDay = Table.RemoveColumns(t,"day"),
//replace all except first event of a type with null
nullEvents = List.Accumulate(t[event],{}, (state,current)=>
if state = {} then {current}
else if List.Contains(state,current) then state & {null}
else state & {current}),
//then create new table and Transpose to get final format
newTable = Table.Transpose(Table.FromColumns(
{nullEvents, t[Value]}
))
in
newTable}
}),
//Calculate number of columns for creating column names
numCols = List.Max(List.Transform(#"Grouped Rows"[#"event & value"], each Table.ColumnCount(_))),
//expand the grouped columns and set the appropriate names
#"Expanded event & value" = Table.ExpandTableColumn(#"Grouped Rows", "event & value",
List.Transform(List.Numbers(1,numCols), each "Column" & Text.From(_)),
List.Transform(List.Numbers(1,numCols), each "e" & Text.From(_))),
//Replace alternate "day" with null
replaceWithNulls = Table.FromColumns(
{List.Accumulate(#"Expanded event & value"[day], {}, (state,current)=>
if Number.IsOdd(List.Count(state))
then state & {null} else state & {current})} &
Table.ToColumns(Table.RemoveColumns(#"Expanded event & value","day")),
Table.ColumnNames(#"Expanded event & value")
),
//set the data types
typeit = Table.TransformColumnTypes(replaceWithNulls,
{{"day", Int64.Type}} & List.Transform(List.RemoveFirstN(Table.ColumnNames(replaceWithNulls),1), each {_, type text}))
in
typeit

How can I get the rows with the most cells that have the highest (or the lowest) values

I have a table of data which is consisted of 18 columns and 2.017 rows. I can get the row that has the highest (MAX) value in a cell but I need the row that has the most cells with higher values and have them in DESC order. I haven't managed yet to find a relevant post to this.
Here follows an example:
Using numbers up to 10 for illustration, the following shows the logic behind. (The actual numbers are those shown in Exhibit1)
Thank you
EDIT:
I am adding the below in order to try to clarify further. I am not sure if it is the correct path to go but I hope it makes sense.
In Exhibit2 I am indexing each column Desc (Based on Exhibit1) and then =SUM in the end of the row. Following this logic, the name having the lowest total is the one with the most high values (not the highest) in its row.
The result table is the following
Although possible with formulas and helper tables/columns, this can also be accomplished using Power Query, available in Windows Excel 2010+ and Excel 365 (Windows or Mac)
To use Power Query
Select some cell in your Data Table
Data => Get&Transform => from Table/Range or from within sheet
When the PQ Editor opens: Home => Advanced Editor
Make note of the Table Name in Line 2
Paste the M Code below in place of what you see
Change the Table name in line 2 back to what was generated originally.
Read the comments and explore the Applied Steps to understand the algorithm
As we discussed in our Chat, I transform each column into a list of Ranked Entries; then sum the ranks for each row and sort as you have laid out.
M Code
let
Source = Excel.CurrentWorkbook(){[Name="Table5"]}[Content],
//type all the columns
data = Table.TransformColumnTypes(Source,{
{"Order", Int64.Type},
{"Name", type text}} &
List.Transform(List.RemoveFirstN(Table.ColumnNames(Source),2), each {_, type number})
),
//Replace with ranks
//generate list of transforms to dynamically include all columns
cols = List.RemoveFirstN(Table.ColumnNames(data),2),
xForms = List.Transform(cols, (c)=> {c, each List.PositionOf(List.Sort(Table.Column(data,c),Order.Descending),_)}),
ranks = Table.TransformColumns(data,xForms),
//add Index column to enable row-wise sums
// then add the sumRank column and delete the Index column
#"Added Index" = Table.AddIndexColumn(ranks, "Index", 0, 1, Int64.Type),
#"Added Custom" = Table.AddColumn(#"Added Index", "sumRank", each
List.Sum(
Record.ToList(
Record.RemoveFields(#"Added Index"{[Index]},{"Order","Name","Index"})
)
)),
#"Removed Columns" = Table.RemoveColumns(#"Added Custom",{"Index"}),
//join back with the original data table
//extract the sumRank column
join = Table.NestedJoin(data,{"Order","Name"}, #"Removed Columns",{"Order","Name"}, "joined",JoinKind.FullOuter),
#"Expanded joined" = Table.ExpandTableColumn(join, "joined", {"sumRank"}, {"sumRank"}),
//sort by the sumRank column, then remove it
#"Sorted Rows" = Table.Sort(#"Expanded joined",{{"sumRank", Order.Ascending}}),
#"Removed Columns1" = Table.RemoveColumns(#"Sorted Rows",{"sumRank"})
in
#"Removed Columns1"
This set-up is volatile, so I would only adopt it if non-volatile alternatives are not forthcoming.
An additional column in your table with the following formula:
=SUM(COUNTIF(OFFSET([Column1],,TRANSPOSE(ROW(INDIRECT("1:"&COLUMNS(Table1[#[Column1]:[Column4]])))-1)),">="&Table1[#[Column1]:[Column4]]))
which you can then use to sort your table.
Note that this formula will most likely require committing with CTRL+SHIFT+ENTER for your version of Excel.
Amend the table and column names as required, noting that the part
Table1[#[Column1]:[Column4]]
as well as including the table name, should comprise the leftmost and rightmost of the contiguous columns to be interrogated.

Copy value inside column based on another column (ID) in Excel or Jamovi

I can't figure out how to make it work. Some people asked similar questions in r-forums but it seems my understanding is to basic to make the transfer.
I have a large repeated measures dataset in long format and i performed a cluster-analysis. Now I need to copy the value signalling group-membership inside the second column based on Participant-ID.
The table underneath shows how it looks at the moment. I need to automatically fill in the blank spaces for cluster_membership with the same values depending on the id.
ID
Cluster_membership
1
1
3
1
2
4
2
3
5
3
ID
Cluster_membership that i need
1
3
1
3
1
3
2
4
2
4
3
5
3
5
Thank you in advance,
Philipp
If your data is as you show it, with only a single Cluster_membership per ID, you can obtain your desired output using Power Query, available in Windows Excel 2010+ and Office 365 Excel
Select some cell in your original table
Data => Get&Transform => From Table/Range
When the PQ UI opens, navigate to Home => Advanced Editor
Make note of the Table Name in Line 2 of the code.
Replace the existing code with the M-Code below
Change the table name in line 2 of the pasted code to your "real" table name
Examine any comments, and also the Applied Steps window, to better understand the algorithm and steps
M Code
let
//change table name in next line to actual name in your workbook
Source = Excel.CurrentWorkbook(){[Name="Table11"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,{{"ID", Int64.Type}, {"Cluster_membership", Int64.Type}}),
//Group by ID and extract Cluster_membership
#"Grouped Rows" = Table.Group(#"Changed Type", {"ID"}, {
{"all", each _, type table [ID=nullable number, Cluster_membership=nullable number]},
{"Cluster_membership", each List.Max([Cluster_membership])}
}),
//remove unneeded columns and expand the resultant table (except for the Cluster_membership column
#"Removed Columns" = Table.RemoveColumns(#"Grouped Rows",{"ID"}),
#"Expanded all" = Table.ExpandTableColumn(#"Removed Columns", "all", {"ID"}, {"ID"})
in
#"Expanded all"
Note:
Another way of getting the same output would be to
Sort the table by ID and then cluster
Fill-Up the cluster column
I'm not sure which will be faster on your data set. The code with sorting is simpler, but sorting sometimes takes a while in PQ. You can try both methods. If you do, please let me know the results of comparison
M Code (sort method)
let
//change table name in next line to actual name in your workbook
Source = Excel.CurrentWorkbook(){[Name="Table11"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,{{"ID", Int64.Type}, {"Cluster_membership", Int64.Type}}),
//sort by ID and cluster, then fill-up
#"Sorted Rows" = Table.Sort(#"Changed Type",{{"ID", Order.Ascending}, {"Cluster_membership", Order.Ascending}}),
#"Filled Up" = Table.FillUp(#"Sorted Rows",{"Cluster_membership"})
in
#"Filled Up"

Move Data in Vertical Cells To Horizontal Cells in Excel 2007

I am using excel 2007
I have a excel sheet with around 1200 records with following structure...
WHAT CAN BE EASIEST WAY TO DO THIS ?
For easy understanding, Adding image :
As per your comment request, here is a Power Query solution.
To enter the code:
Select some cell in your Data Table
Data => Get&Transform => from Table/Range
When the PQ Editor opens: Home => Advanced Editor
Make note of the Table Name in Line 2
Paste the M Code below in place of what you see
Change the Table name in line 2 back to what was generated originally.
Algorithm
Fill in (fill down) the blank rows for the District and Branch columns
Group by District and Branch
For each Group, extract as a delimited string the entries for President, Secretary and Treasurer.
Create the appropriate column names and split the delimited strings into separate columns.
If you have more officers, or more items per officer/position, or more columns before you get to the officer columns, it should be relatively simple to modify the code to take that into account.
M Code
let
Source = Excel.CurrentWorkbook(){[Name="Table16"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,{{"District", Text.Type}, {"Branch", type text},
{"President", type text}, {"Secretary", type text}, {"Treasurer", type text}}),
#"Filled Down" = Table.FillDown(#"Changed Type",{"District", "Branch"}),
#"Grouped Rows" = Table.Group(#"Filled Down", {"District", "Branch"},{
{"President", each Text.Combine([President],";")},
{"Secretary", each Text.Combine([Secretary],";")},
{"Treasurer", each Text.Combine([Treasurer],";")}
}),
colHeaderSuffix = {"","Addr","Mobile"},
PresidentCols = List.Accumulate(colHeaderSuffix, {}, (state, current) => List.Combine({state, {"President " & current}})),
#"Split Column by Delimiter" = Table.SplitColumn(#"Grouped Rows", "President",
Splitter.SplitTextByDelimiter(";", QuoteStyle.Csv), PresidentCols),
SecretaryCols = List.Accumulate(colHeaderSuffix, {}, (state, current) => List.Combine({state, {"Secretary " & current}})),
#"Split Column by Delimiter2" = Table.SplitColumn(#"Split Column by Delimiter", "Secretary",
Splitter.SplitTextByDelimiter(";", QuoteStyle.Csv), SecretaryCols),
TreasurerCols = List.Accumulate(colHeaderSuffix, {}, (state, current) => List.Combine({state, {"Treasurer " & current}})),
#"Split Column by Delimiter3" = Table.SplitColumn(#"Split Column by Delimiter2", "Treasurer",
Splitter.SplitTextByDelimiter(";", QuoteStyle.Csv), TreasurerCols)
in
#"Split Column by Delimiter3"
Original Data
Results
Formula Used as follows (Giving solution here so in future members can use it)
The formula is : In empty cell after Treasurer Column,
=If($a2="","",a2) // copy over next 4 columns to give the District, Branch, Pre name, address, mobile elements as =If($a2="","",a2), =If($b2="","",b2), =If($c2="","",c2), =If($c2="","",c3), =If($c2="","",c3), =If($c2="","",c4)
=if($d2="","",d2) // copy over next 2 columns for Secretary details like =if($d2="","",d2), =if($d2="","",d3), =if($d2="","",d4)
=if($g2="","",g2) // copy over next 2 columns for Treasurer details like =if($g2="","",g2), =if($g2="","",g3), =if($g2="","",g4)
Now Select All New Formula Cells in a row after Treasurer column >> Drag Down Till All Records....
Then Copy all these down to the bottom of your data
Either copy / paste special >> values to somewhere else and
Then sort by District / Branch / Pres to drop the blank rows
I don't know if your excel pc will be able to handle it but you can use the [Paste Transpose][1].
You copy everything, (my advice, go to a new spreadsheet, but you can use the same one),
and then you past it use past transform
*edit
after you edited your question with the example you might want to use the past transform and then use pivot table

Concatenate power query columns that are offset from each other

The problem
I have a data set with two header rows. I've transposed the rows into columns to work with the headers before combining, but I need help with concatenation of column1 into column2, since past row 7 the columns are offset from one another by one row (see example image).
The goal
I've tried to use replace and concatenate myself with an index, but have been unable to achieve the desired end result where column2 row 8 is concatenated with column1 row 7, so that when I combine these columns and transpose again the headers will be correctly labeled (see example image).
Thank you for any suggestions and your time.
Example image:
Here's one way.
I start with your Problem table as a table named Table1:
Then I add an index. (Add Column > Index Column):
Then I add a custom column. (Add Column > Custom Column) With this setup:
(#"Added Index"{[Index]-1}[Column1] references the entry in Column1 at the position record row that is equal to the value in the Index column, minus 1.)
...to get this:
Then I replaced Errors in the new Custom column. (Right-click Custom column title > click Replace Errors > type null > click OK)
Then I select Column1 and Custom column and remove other columns. (Select Column 1 column title > hold Ctrl and click Custom column title > keep holding Ctrl and right click Custom column title > click Remove Other Columns)
Here's my M code:
let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,{{"Column1", type text}, {"Column2", type text}}),
#"Added Index" = Table.AddIndexColumn(#"Changed Type", "Index", 0, 1),
#"Added Custom" = Table.AddColumn(#"Added Index", "Custom", each #"Added Index"{[Index]-1}[Column1]&"-"&[Column2]),
#"Replaced Errors" = Table.ReplaceErrorValues(#"Added Custom", {{"Custom", null}}),
#"Removed Other Columns" = Table.SelectColumns(#"Replaced Errors",{"Column1", "Custom"})
in
#"Removed Other Columns"
Another way.
Code:
let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
IndexedTable = Table.AddIndexColumn(Source, "Index", 0, 1),
Transform = Table.TransformRows(IndexedTable, (row)=>[Column1= row[Column1], Column2 = if row[Column1]=null then Text.Combine({IndexedTable{row[Index]-1}[Column1], "-",row[Column2]}) else row[Column2]]),
ToTable = Table.FromRecords(Transform)
in
ToTable
Brief explanation:
Source
Add index to address previous record
Use Table.TransformRows to analyze and transform each row to a record in this manner: Column1 taken from each row's column1 (row[Column1]), Column2 is generated from previous row using Text.Concatenate, IndexedTable{row[Index]-1}[Column1]. This yields value from previous row's Column1. Table.TransformRows returns list of records.
Transform list of records into the table.
This code will fail if 1st row contains null in [Column1]. If this is unacceptable, add another if-then-else.
Another way:
let
Source = Excel.CurrentWorkbook(){[Name="Table"]}[Content],
fillDown = Table.FillDown(Table.DuplicateColumn(Source, "Column1", "copy"),{"copy"}),
replace = Table.ReplaceValue(fillDown, each [Column2], each if [Column2] = null then null
else [copy]&"-"&[Column2], Replacer.ReplaceValue, {"Column2"})[[Column1],[Column2]]
in
replace

Resources