PowerQuery multiple files and add column - excel-2010

I have the inline PowerQuery to automate my weekly reporting. Since I am new to power query I followed up this tutorial and try to add a custom column so I can use it to see week over week improvements, the thing is that the column that is added is not named "Week" but instead it is called the name of the file. From this webpage the second parameter is column name. I do not find why column name is filename instead of the name "week".
let ExcelFile = (FilePath, FileName) =>
let
Source = Folder.Files(FilePath),
File = Source{[#"Folder Path"=FilePath,Name=FileName]}[Content],
ImportedExcel = Excel.Workbook(File),
Sheet1 = ImportedExcel{[Name="Page1_1"]}[Data],
TableWithWeek = Table.AddColumn(Sheet1,"Week", each FileName),
TableWithoutHeader = Table.Skip(TableWithWeek,3),
FirstRowAsHeader = Table.PromoteHeaders(TableWithoutHeader)
in
FirstRowAsHeader
in
ExcelFile

This call:
FirstRowAsHeader = Table.PromoteHeaders(TableWithoutHeader)
will replace the column names you have with the values from the first row. Since the first value under the column "Week" is the filename, then your table will now use that filename as the column name.
You can fix this by adding the custom column after you use PromoteHeaders:
let ExcelFile = (FilePath, FileName) =>
let
Source = Folder.Files(FilePath),
File = Source{[#"Folder Path"=FilePath,Name=FileName]}[Content],
ImportedExcel = Excel.Workbook(File),
Sheet1 = ImportedExcel{[Name="Page1_1"]}[Data],
TableWithoutHeader = Table.Skip(Sheet1, 3),
FirstRowAsHeader = Table.PromoteHeaders(TableWithoutHeader),
TableWithWeek = Table.AddColumn(FirstRowAsHeader,"Week", each FileName),
in
TableWithWeek
in
ExcelFile

Related

Lua: Saving and opening a two dimensional table indexed by key

Apologizes if the semantics is erroneous in my question, but the code below should explain what my goal is.
I've created a table like so:
local a1 = {}
a1.hammer = {
price = 10,
quantity = 5,
category = "tools",
}
a1.saw = {
price = 15,
quantity = 4,
category = "tools",
}
a1.screwdriver = {
price = 4,
quantity = 12,
category = "tools",
}
Printing the contents of this table gives:
{hammer = {price = 10,
quantity = 5,
category = "tools"},
saw = {price = 15,
quantity = 4,
category = "tools"},
screwdriver = {price = 4,
quantity = 12,
category = "tools"}}
Question 1: How do I access the price of the screwdriver (ie. field of a table of a table)
Question 2:
How do I:
Save table a1 to a file
Open the file and import the table the next time I run the application
Note: local a2 = a1 returns nil for a2 rather than assigning the reference of a1 to a2. There's an issue here...
#Luke Allison
I may have an answer to your first question:
Question 1: How do I access the price of the screwdriver (ie. field of
a table of a table)
you can try this code:
print( a1["screwdriver"]["price"] )
Result = 4.
As for the second question you should have a look at the link in the comments above.
Hope that helps.

How to generate Excel form EPPluse which has group column header

I want to generate excel sheet from EPPluse which has group column header like below picture.Then How to build DataTable which handle this situation. please help me to get it done easily.
Thanks in advance
You want to use the Merge property on the ExcelRange object.
Here's an example:
using (var pck = new ExcelPackage(new FileInfo(#"c:\temp\Book1.xlsx")))
{
var ws = pck.Workbook.Worksheets["Sheet1"] ?? pck.Workbook.Worksheets.Add("Sheet1");
var rng = ws.Cells["BO1:BQ1"];
rng.Merge = true;
rng.Value = "Answer for Att 3";
pck.Save();
}
You can use this code to write your group headers, then use ExcelRange's LoadFromDataTable() method to write your DataTable directly to the worksheet starting from cell A2

google sheet formula - get column letter by variable?

Given a formula, eg:
= FILTER(matrix!B3:B99, NOT(matrix!C3:C99 = "") ) )
Is it possible to pass a variable in place of column B reference? Eg:
= FILTER(matrix!$requiredCol3:$requiredCol99, NOT(matrix!C3:C99 = "") ) )
where $requiredCol is whatever value is always in A1 for example?
eg, A1=X
formula is now equivilent to:
= FILTER(matrix!$X3:$X99, NOT(matrix!C3:C99 = "") ) )
Thanks
You should be able to use INDIRECT(), which takes a cell reference as string as (first) parameter. See if this works:
= FILTER(INDIRECT("matrix!"&A1&"3:"&A1&"99"), NOT(matrix!C3:C99 = "") )
EDIT: if you have the ranges in cells A1 and A2 try
=FILTER(INDIRECT(A1), INDIRECT(A2) <>"")

Concatenate certain rows into a cell ignoring duplicates

I have a google form and I would like to sort it's responses in a separate sheet on google sheets. The results of the form look sort of like this.
Id Job
1 Shelving, Sorting
2 Sorting
1 Cleaning, Shelving
3 Customer Service
2 Shelving, Sorting
which I would like to format into
Id Jobs
1 Cleaning, Shelving, Sorting
2 Shelving, Sorting
3 Customer Service
Is there a formula I can use to accomplish this, noting that it ignores duplicates and groups the different ids? Ordering of the jobs does not matter.
Working example here.
The code is like:
=unique(transpose(split(join(", ",filter(B1:B10,A1:A10=1)),", ")))
where
filter(B1:B10,A1:A10=1) gives you all the B values where A = 1
join(",", filter(...)) joins the list with the ", " separator (e.g. "apple, orange" and "kiwi" becomes "apple, orange, kiwi"
split(join(...)) splits the list into an array (e.g. back to [apple, orange, kiwi]
transpose(split(...)) converts the horizontal list to vertical list
unique(transpose(...)) gives you the unique values (unique() only works with vertical list)
After this, you need to transpose then join the list
Note you must keep the separator consistent (e.g. always "," or ", ")
This is Apps Script code instead of a function. To use it, you will need to use the Tools menu, and open the script editor. Then select the function name from the drop down list, and then click the "Run" button.
To use this code, you need to have a source and a destination sheet. You will need to change the sheet names in the code to your sheet names. In this code, the source sheet is named 'Data'. You will need to change that to the name of your source sheet. In this code, the destination sheet is named 'Output', and is at the bottom of the code. This code gets data starting in row two, and writes the output data starting in row two. I tested it with your values and it works.
function concatCellData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getSheetByName('Data');
var colOneData = sh.getRange(2, 1, sh.getLastRow()-1, 1).getValues();
var colTwoData = sh.getRange(2, 2, sh.getLastRow()-1, 1).getValues();
var newData = [],
newDataColOne = [],
colOneValue,
existInNewData = false,
colB_One,
colB_Two,
dataPosition,
thisValue,
combinedArrays = [],
arrayTemp = [];
for (var i=0;i<colOneData.length;i+=1) {
colOneValue = colOneData[i][0];
dataPosition = newDataColOne.indexOf(colOneValue);
existInNewData = dataPosition !== -1;
if (!existInNewData) {//If it doesn't exist in the new data, just write the values
newDataColOne.push(colOneValue);
newData.push([colOneValue, colTwoData[i][0]]);
continue;
};
colB_One = [];
colB_Two = [];
combinedArrays = []
arrayTemp = [];
colB_One = colTwoData[i][0].split(",");
colB_Two = newData[dataPosition][1];
colB_Two = colB_Two.split(",");
var combinedArrays = colB_One.concat(colB_Two);
//Get unique values
for (var j=0;j<combinedArrays.length;j+=1) {
thisValue = combinedArrays[j].trim();
if (arrayTemp.indexOf(thisValue) === -1) {
arrayTemp.push(thisValue);
};
};
newData[dataPosition] = [colOneValue, arrayTemp.toString()]; //Overwrite existing data
};
ss.getSheetByName('Output').getRange(2, 1, newData.length, newData[0].length).setValues(newData);
};

Reading Excel using C# and OleDB - How to identify the used range?

I am reading an Excel file using good old OleDBConnections and OleDBCommands. How do I identify the used range of the excel sheet?
For example, if I were to use InterOp, I can always do this -
Excel.Application xlApp = new Excel.Application();
Excel.Workbook xWb;
Excel.Worksheet xWs;
Excel.Range range;
xWb = xlApp.Workbooks.Open(#"D:\Technical\C#\WorkingFolder\HelloWorld.xls", 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);
xWs = (Excel.Worksheet)xWb.Worksheets.get_Item(1);
range = xWs.UsedRange;
Now, I get a list of all the used columns. With OleDB, how do I get it. Now, even if I were to nail down the column list, how will I know that the rows end here.
Basically, my requirement is this.
I am about to receive an Excel (2003) file. The data will always include Headers (i.e., column name). It does not mean that the data will always be populated from A1:J200
It can also be from A5:J204 too.
So, in using OleDBCommand
string sConnectionString = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:\Technical\C#\WorkingFolder\HelloWorld.xls;Extended Properties=""Excel 8.0;HDR=YES;""";
string sCommandString = "SELECT Employee_Id, First_Name FROM [Sheet1$A1:J200]";
OleDbConnection xlConnection = new OleDbConnection(sConnectionString);
xlConnection.Open();
OleDbCommand xlCommand = new OleDbCommand(sCommandString, xlConnection);
OleDbDataAdapter tempDataAdapter = new OleDbDataAdapter();
tempDataAdapter.SelectCommand = xlCommand;
DataTable tempDataTable = new DataTable("Whatever_I_Want");
tempDataAdapter.Fill(tempDataTable);
Now, the line
sCommandString has the hardcoded value of A1:J200, what if the excel I receive has the data range as A5:204, what will I do?
Any help would be great!
Untried but I think you could do it by first creating a DataAdapter with a SELECT * FROM [Sheet] statement and then use that in a call to FillSchema after which you should be able to call .Columns.Count on the DataTable you just filled.

Resources