I'm trying to get the subtotals for a table in C# using Microsoft.Interop.Excel, and there is a built in function for that.
[Here][1] is the link to the documentation for the Subtotal function.
I understand what GroupBy and Function parameters do, but what exactly is the TotalList parameter for? Microsoft describes it as:
"An array of 1-based field offsets, indicating the fields to which the subtotals are added."
How are these offsets being read? In pairs for row and column offset? In examples I see whole arrays of many numbers being used for this. How do I make use of this?
[1]: https://learn.microsoft.com/en-us/dotnet/api/microsoft.office.interop.excel.range.subtotal?view=excel-pia
You pass an array of as many numbers as you have columns for which you want subtotals calculated. If you only have one column to subtotal, you can just pass in a single number in place of an array (at least, in VBA that works)
Eg: (in VBA) -
Range("A1").CurrentRegion.Subtotal GroupBy:=1, Function:=xlSum, TotalList:=Array(3, 5)
would group a table of data starting in A1, according to the first column, and add subtotals in the third and fifth columns.
Related
Using C# .Net Google Sheets API.
I am new to the API, so I may have missed it in the docs - but how do you find out the maximum row and column that contain a value without reading all the data in the sheet?
For example, if a sheet contains multiple values and the "last" cell in the sheet with a value is at C139 (no cells in the rows following have a value and no cells in any column after C have a value), then the maximum row would be 139 and the maximum column would be 2 (zero based) or 3 (one based).
I tried sheet.Properties.GridProperties.RowCount -- but that gives the TOTAL number of rows in the sheet (whether the cells have values or not).
Same goes for sheet.Properties.GridProperties.ColumnCount -- gives the TOTAL number of columns in the sheet (whether the cells have values or not).
Any links or ideas are welcome.
I understand that you want to know the last row of data in your Sheet. In that case, you can use a simple GET with a full range. For example let's assume that your Sheet only has two columns, in that case you can set up the range like A1:B. That range will include the full two columns, but the get will only get as far as the data goes. At this step you already have an array filled with your data range, so you only have to count the array index of the last element in order to know the last row value. If you don't know how many columns your Sheet have, you only have to modify the range in a similar way as before (i.e. A1:Z). Please ask me any doubts about this approach.
I am looking for a creative way to essentially chunk a multi-format csv file into data structures.
For instance here is my csv
FILEHEADER;00;RSRGP;12345;20130415;
542740;60;FRED ROGERS;1Z7539320359483792;4000001388;20130415;0000000800;0000000000;UPS;Grnd;
542740;70;511-59049-019;00001;00001;
542740;80;000000001;000000001;
542740;60;FRED ROGERS;1Z753932032184736528;4000002092;20130415;0000000000;0000000000;UPS;Grnd;
542740;70;511-56957-019;00001;00001;
542740;70;511-58714-019;00002;00002;
542740;70;511-58715-188;00001;00001;
542740;70;511-58717-019;00002;00002;
542740;70;511-58722-188;00001;00001;
542740;80;000000007;000000007;
FILETRAILER;99;0000022;
As you see there are different record types in the csv. This is generally indicated by the second column (00, 60, 70, 80 99). Rows with a record type of 60 indicate an order header and include a tracking number in the 4th column. The order id is indicated in the first column of record types 60 and 70. So I have one order with multiple packages.
I'd like a good way to take the first order header and it's associated order line items (Record type 70) and shove it into a data structure, then take the next order header and it's associated line item and shove it into another data structure of the same type.
It's not as trivial as I first thought and now I've been staring long enough that I think I am lost in the trees.
Any suggestions would be greatly appreciated.
Does it have to be Linq?
You can read the value line by line, and then use the .split(';') method of the line/string to split it into an array of substrings.
You can then check the value of the appropriate array entries and use these to fill up your data objects.
I have a datagridview displayed on the screen. The user can change the end column called "Pareto" to any integer he/she likes. But there is a catch, all records are in a league.
The user also may wish to simply leave a number out and come back to it, so not allowing for a missing number isn't possible.
Basically I need a method that checks if a column has a missing number from a non-sorted row, and also stores each number that's missing into an array/list for me to output.
Normally I like these little logic questions But after the loops I've coded today my brain is burnt out... so any input would be great!
I originally thought about first getting the maximum records in the grid via count(no problem)
Then using it as the range from 1 - "maxCount". Find all missing numbers. It sounded so simple until I thought about the fact it is not sorted.
Many thanks
Not clear the real work-flow, but..
The fact is that DataGridView is not sorted is a pure UI stuff. Your data can be sorted and binded to the DataGrid via DataView or any other intermidiate View layer.
One time user inserts the value, you can execute binary-search (fastest available on sorted collection search) to find the value of interest.
EDIT
If you need to check the missed numbers among set of numbers from (1..500), first you can have all numbers sorted, like defined in my post in data-model.
List<int> sortedAlreadyAvailableNumbers ...
after make
var missingNumbers = Enumerable.Range(1, 500).Except(sortedAlreadyAvailableNumbers );
Hope this helps.
I have an object structure that is mimicking the properties of an excel table. So i have a table object containing properties such as title, header row object and body row objects. Within the header row and each body row object, i have a cell object containing info on each cell per row. I am looking for a more efficient way to store this table structure since in one of my uses for this object, i am printing its structure to screen. Currently, i am doing an O(n^2) complexity for printing each row for each cell:
foreach(var row in Table.Rows){
foreach(var cell in row.Cells){
Console.WriteLine(cell.ToString())
}
}
Is there a more efficient way of storing this structure to avoid the n^2? I ask this because this printing functionality exists in another n^2 loop. Basically i have a list of tables titles and a list of tables. I need to find those tables whose titles are in the title list. Then for each of those tables, i need to print their rows and the cells in each row. Can any part of this operation be optimized by using a different data structure for storage perhaps? Im not sure how exactly they work but i have heard of hashing and dictionary?
Thanks
Since you are looking for tables with specific titles, you could use a dictionary to store the tables by title
Dictionary<string,Table> tablesByTitle = new Dictionary<string,Table>();
tablesByTitle.Add(table.Title, table);
...
table = tablesByTitle["SomeTableTitle"];
This would make finding a table an O(1) operation. Finding n tables would be an O(n) operation.
Printing the tables then of cause depends on the number of rows and columns. There is nothing, which can change that.
UPDATE:
string tablesFromGuiElement = "Employees;Companies;Addresses";
string[] selectedTables = tablesFromGuiElement.Split(';');
foreach (string title in selectedTables) {
Table tbl = tablesByTitle[title];
PrintTable(tbl);
}
There isn't anything more efficient than an N^2 operation for outputting an NxN matrix of values. Worst-case, you will always be doing this.
Now, if instead of storing the values in a multidimensional collection that defines the graphical relationship of rows and columns, you put them in a one-dimensional collection and included the row-column information with each cell, then you would only need to iterate through the cells that had values. Worst-case is still N^2 for a table of N rows and N columns that is fully populated (the one-dimensional array, though linear to enumerate, will have N^2 items), but the best case would be that only one cell in that table is populated (or none are) which would be constant-time.
This answer applies to the, printing the table part, but the question was extended.
for the getting the table part, see the other answer.
No, there is not.
Unless perhaps your values follow some predictable distribution, then you could use a function of x and y and store no data at all, or maybe a seed and a function.
You could cache the print output in a string or StringBuider if you require it multiple times.
If there is enough data I guess you might apply some compression algorithm but I wouldn't say that was simpler or more efficient.
oSheet = (Excel._Worksheet)xlWorkBook.ActiveSheet;
oRng = oSheet.get_Range("T10", "T343");
The range oRng contains values of type double. Each cell in Column T shows the max number of the associated row. How can i find out how many 1’s , 2’s 3’s ….. till 10 are in that range. Secondly Eg if there are 20 rows with value =3 , I need to copy column A,B,C from those rows and store them for later use .i need the count of the number of rows for each value from 1 to 10
Here are a few general observations that might be enough to get you going:
Excel.Range has an AutoFilter method that you might be able to employ successively for each value that you're interested in (i.e, 1 through 10). Once you have the individual ranges returned by AutoFilter, you can them query them for the specific information you're interested in. See C# Excel Automation: Retrieving rows after AutoFilter() with SpecialCells() does not seem to work properly for issues associated with this approach.
Alternatively, you might be able to do something like create a simple dictionary that you could then populate as you iterate over column T. For example, the dictionary could be of type Dictionary>.
As you proceed through column T, you encounter a value in each cell. If the cell value hasn't been seen before, you add it as a new key to the Dictionary. For the associated value in the dictionary's key/value pair, you create a new List with the corresponding row number as its first element.
If the cell value has been seen before, you look it up in the dictionary, then add the corresponding row to the List associated with that key.
At the end of the day, your dictionary's keys contains all the values found in column T. The number of rows associated with each value is just the number of elements in the associated List. With the row values in the List, you can then find "A[row value]", "B[row value]" and "C[row value]".