Using OpenXML, you can get a list of the named ranges in an Excel document using something similar to:
IEnumerable<DefinedName> names = document
.WorkbookPart
.Workbook
.DefinedNames
.Cast<DefinedName>();
Each of these DefinedName's has a Text property, which defines the range that it refers to, e.g.
Sheet1!$B$3:$D$8
which we can then parse, and use to retrieve the data. At least that's how I understand the process so far.
However, with a dynamic range, the text property can contain something like:
OFFSET(Sheet1!$F$3,0,0,COUNTA(Sheet1!$F:$F),1)
This is not a range, it is a formula which returns a range, and it is the result of this formula that I need.
Is it possible to calculate this formula, or is the result already stored somewhere in the spreadsheet that I can read? Or is there some other way in which I can read a dynamic named range?
This question is specifically about OpenXML. I know that it can be done using other tools.
Excel Defined Names are really named formulas rather than named ranges. So you would need a method such as VBA Evaluate to coerce the formula to a range or a result.
AFAIK OpenXML does not have such a method, so you would have to write your own formula parser and evaluator, or use some other tool.
Related
I have an Excel file that contains lots of data, and I'm making a program that reads the excel file, does some statistics, and prints the findings in console.
I need to count the occurrences of a specific string, in a specific column, and save the result to a variable in code.
I've thought of using excel's COUNTIF() formula, but it seems like I have to put the formula in a cell, to read the result, and therefore cant just assign a variable to it's result.
How can I do the same thing as COUNTIF() without modifying the file?
I want to convert some spreadsheets which contain references to a plugin-defined function which we are trying to remove. There is a method to convert this which works in VBA by using SUMIFS and generating a table
I am at the step where I have parsed the formulas and extracted the parameters used for the function (done by bracket counting). I have hit a snag. How do I get NPOI/POI Apache to evaluate the things. It seems to demand everything be done inside a cell. This isn't possible in this scenario (since these are parameters not cell formulas, so they don't have a cell in which to evaluate them).
There is the OperandResolver class which seems to be along the right lines, but it wants a ValueEval type as its input which I can't figure out at all. Currently I can only get the parameters as strings. Like "A1", "0.9", "SomeOtherFunction(...)" etc. Those are what I have.
Basically I need something like
pseudocode:
var result = Evaluate_Formula_String(string formula, var Contextual_Information_eg_current_Worksheet)
Where the result would contain either a string or something easily converted into a string.
The function you need seems to be simply Application.Evaluate. It takes a string and evaluates it.
Reference page: https://learn.microsoft.com/en-us/office/vba/api/excel.application.evaluate
I hope someone can help me. Is there a way to embed a specific file (.txt) into an excel cell? I'm currently using epplus, and I would like to embed programmatically a file into a specific excel cell. I did manage to add a hyperlink, but my goal is to have it embedded.
Worksheet.Cells[rowNumber, colNumber].Value = ....
Is there any way to do it? I couldn't find anything online.
As mentioned in the comments, you can certainly put text within a cell, but bear in mind Excel does have a limit to the number of characters it will allow in a single cell. It's pretty large, but conceivably the contents of a text file could exceed that limit -- even if future versions of Excel keep increasing what the limit is (as they have in the past).
You can also embed an OLE object in your worksheet, and a text file qualifies for that. I don't know that you can assign it to a cell, per se. You can change the location, shape and behavior to fit in a cell and behave as though it's part of a cell, but I don't know that it ever belongs to a range the way formulas do. I could be wrong.
The basic construct of how to embed an OLE object into a worksheet is as follows:
Excel.OLEObject ole = ws.OLEObjects().Add(Filename: #"C:\Users\hambone\Documents\foo.txt");
This is the equivalent of the VBA:
Set ole = sh.OLEObjects.Add(Filename:="C:\Users\hambone\Documents\foo.txt")
The method returns an OLEObject object, which you can then shape to behave the way you want:
ole.Height = 5;
I'm opening up xlsx files as a package and reading the contents of the xml files. I'm able to get the shared strings, borders, etc that I need and it's orders of magnitude faster than when I was using Interop. The only issue I have is when it comes to pulling out numbers and formatting them properly based on what the formatting is in the Excel file.
Is there a generic function somewhere that takes a value and a format and returns the formatted string? For example, if I have the value 31502008 and the custom format "$* #,##0_);$* (#,##0)" is there a simple way to get what Excel shows (which is $31,502,008). Obviously Excel knows how to handle it, but I have some sheets that have a crazy number of custom formats and I'm wondering how best to ensure that the string I get back in code matches what is seen in Excel.
Any ideas?
Thanks a lot for any help.
I've been googling and searching on the site for the answer, but I couldn't find a solution - everywhere people mostly discuss how to add new number format to the document and apply it.
What I need is to get the cell value as a string with applied formatting - i.e. same string as would be displayed by Excel.
I already figured that there's no easy way or built-in function which would return the readymade formatted value for a cell.
So it seems to me that to get the value I need to do two things:
1. Get the format string.
2. Format the cell value using this string.
But I have problems with both steps.
One can easily get CellFormat instance which would contain NumberFormatId:
CellFormat cellFormat = (CellFormat) document.WorkbookPart.WorkbookStylesPart.Stylesheet.CellFormats.ElementAt(cell.StyleIndex);
But how to get the format string with this NumberFormatId, if the id corresponds to one of standard predefined formats? (i.e. is below 160) They are not in the spreadsheet document and I can't believe that they should be hardcoded in the application.
Also, once the format string is somehow obtained, how to apply it to the cell value? So far I understand, the code should check the type of the cell value and if is Number - convert it to string using the format string.
I found this page which mentions using Microsoft.Office.Excel.Interop, but I would prefer to stay with OpenXML SDK only.
Overall, I'm very surprised that it's so difficult to find a definitive answer to this question on the Web as I thought that this would be something which many developers need in their daily work.
Men, this is a hard one... I will be adding here things that i found that could be worth..
First is to get the numbering format of the cell (once you have the CellFormat:
string format = excel.WorkbookPart.WorkbookStylesPart.Stylesheet.NumberingFormats.Elements<NumberingFormat>()
.Where(i => i.NumberFormatId.ToString() == cellFormat.NumberFormatId.ToString())
.First().FormatCode;
For more information about this you can go to: NumberingFormats
Im trying to find out how to apply this format to the cell.CellValue property... I think thats the way you have to go!
Ok, reading the ClosedXml code (its open source), seems to be easy to get the format.
Simply convert the value text to its type (int, double, etc) and call the ToString method passing the format. I was trying do that with the String.Format and didnt work. Ive tested the ToString and it works, but something still missing.
I recommend to you to look at this class and get the code from the method GetFormattedString() as #El G tell in his comment.
Bassicaly you will have to add something like this:
double d = double.Parse(cell.CellValue.InnerText);
string val = d.ToString(format);
Hope it helps you...
If you want to take cell value with applied formatting, same as displayed in Excel, use .Text property of Cell object. Like this:
String formattedValue = cell.Text