I am using Epplus library to add conditional formatting to an existing Excel spreadsheet with the following code:
var conditionalFormatting = worksheet.Cells[address].ConditionalFormatting.AddExpression();
conditionalFormatting.Formula = $"=IF(EXACT(A1, \"\"), IF(EXACT(B1, \"\"), TRUE, FALSE), FALSE)";
conditionalFormatting.Style.Fill.BackgroundColor = errorColor;
This code seems to be working fine since when I open the spreadsheet with Excel 2016 I can see the appropriate behaviour.
My Question
On opening the same spreadsheet with Excel 2010, I get this message:
Excel found unreadable content in 'Spreadsheet.xlsx'. Do you want to recover the contents of this Workbook?
Recovering the contents: Excel prompts with:
Removed Feature: Conditional formatting from /xl/worksheets/sheet1.xml part
Did this ever happen to anyone else? I think EPPlus library should work fine with Excel 2007+
Does anyone know of any workaround?
Try removing the = sign from the Formula.
conditionalFormatting.Formula = $"IF(EXACT(A1, \"\"), IF(EXACT(B1, \"\"), TRUE, FALSE), FALSE)";
By adding the = it would result in the formula to be shown as ==IF(EXACT... which is invalid. Formulas for conditional formatting are not stored with the beginning = sign. If this still works in Excel 2016, maybe it accepts/ignores the extra =?
Related
I am having issue reading in some worksheet from a workbook using C# and EPPlus.
Error Message
name contains invalid characters
Even after multiple checks on the worksheet name, file name and column headers within the workbook to make sure there is no invalid characters, I am still facing the same error.
However, when I move the worksheet that i need from that same workbook to a new Excel file and save it with the same file name and worksheet name, I have no error while reading in.
Does anybody know how to solve or even encounter this problem?
Code
using (ExcelPackage xlPackage = new ExcelPackage(mStream))
{
//WorksheetId = 5
var ws = xlPackage.Workbook.Worksheets[WorksheetId]; //This is the part that is causing error
for (int i = 1; i <= ws.Dimension.End.Column; i++)
{
dt2.Columns.Add((i - 1).ToString());
}
}
Came across this LINK and realized this is actually a bug in EPPlus for version 4.5.2.2 onward.
After reverting back to the older version, everything works fine.
There is a change the "name" as mentioned in the error is not the sheet name.. There is a section in the Formular tab of the Excel software called "Name Manager".
There you will find list of names and references there. The error above per the source code of EPPlus is generated when EPPlus tries to validate the name range.
I had to modify the EPPlus source code to ignore the error since the file i was dealing with was locked and needed to be preserved as it was.
I have a C# application which purpose is to store a big amount of data. I am using Microsoft.Office.Interop.Excel (Microsoft.Office.Interop.Excel.dll Version 14.0.0.0) to help me accomplish this. I have Excel 2007 installed.
I use the following lines:
excelApp = new Microsoft.Office.Interop.Excel.Application();
excelWorkBook = excelApp.Workbooks.Add(misValue);//*--------> LINE NOT WORKING */
excelWorksheetBeingWritten = (Excel.Worksheet)excelWorkBook.Worksheets.get_Item(1);
My code then iterates through a big list of objects, and each time a row must be written I do something like:
var startCell = excelWorksheetBeingWritten.Cells[excelLineCounter, 1];
var endCell = excelWorksheetBeingWritten.Cells[excelLineCounter, 2];
string[] tmpArray = new string[2] { stringVar1, stringVar2 };
tmpRange = excelWorksheetBeingWritten.Range[startCell, endCell];
tmpRange.Value = tmpArray;
When excelLineCounter exceeds 65536, the "HRESULT: 0x800A03EC exception" is thrown. I am perfectly aware of the (in)famous pre-Excel2007 row limit (which is precisely 65536). What I don't understand is why the interops are using that limit, when Excel 2007 (my version) has a documented limit of 1.048.576 rows.
On the other hand, if I replace the above "LINE NOT WORKING" by the following, it seems to use the Excel 2007 row limit, and the exception vanishes:
excelWorkBook = excelApp.Workbooks.Open(#"H:\Workbook1.xlsx");//*--------> LINE WORKING */
Note: "Workbook1.xlsx" is an empty workbook previously saved as "Excel Workbook (*.xlsx)"
Can someone please tell me what kind of sorcery do I need to do in order to configure the Excel Interop objects to use the Excel 2007 limits by default, preferably without having a previously saved empty .xlsx file laying around?
I encountered a similar issue yesterday and the solution is to change your Excel settings to create xlsx files by default.
In Excel: File -> Options -> Save -> Save files in this format
Your default is probably 'Excel 97-2003 (*.xls)' like mine was. If you change it to 'Excel Workbook (*.xlsx)', your code will work.
I need to create a "Document level customization" with C# code (not and Excel Add-in!)
I created a Visual Studio Office Excel 2010 Workbook project type. This creates a workbook with 3 sheets in my project. I added some "configuration" information to one of those sheets.
I need to access this configuration information programmatically (Sheet1 contains a button - pressing on that button should
load configuration data
open a WinForm
present configuration data on that form,
but somehow I can't find how to do that...
If I try to initialize Sheet1 class, compiler expects two parameters - Microsoft.Office.Tools.Excel.Factory and IServiceProvider, but I am calling this from a button that is placed on Sheet2 - so it's after Excel Workbook is already opened... shouldn't Sheet1 be initialized automatically?
So, how can I access Sheet1 from my VSTO project's c# code?
EDIT
Please see project sample screencast here
I have a button on Sheet2, that should
load some data from Sheet1
initialize WinForm
add it as a DataSource for a ComboBox on that WinForm
I can not find a way how to read data from that Sheet1...
It seems, that there are not a lot developers (at least at stackoverflow) that work with Excel workbooks in Visual Studio / VSTO), but still this is is how I got this basic stuff working - in case if this is helpful to someone else
Since my code was in the Worksheet's *.cs file it turned out I can access project's xlsx file this way:
var excel = (Excel.Application)this.Application;
var xlbook = (Excel.Workbook)excel.ActiveWorkbook;
var worksheets = xlbook.Worksheets;
var sheet = (Excel.Worksheet)worksheets["Sheet3"];
int row = 2;//1st row for column titles
while (!string.IsNullOrEmpty(((Excel.Range)sheet.Cells[row, 2]).Value))
{
var weight = ((Excel.Range)sheet.Cells[row, 3]).Value;
row++;
}
Some additional things about processing data from Excel sheet in c# code, I found out (maybe that's helpful for someone):
the .NET type for Excel Cell is Excel.Range (at least I didn't
find any other option)
when reading cell that is empty in Excel file, it's value on .NET side is null, not ""
values that seem to be strings on Excel side - can turn to be different types when loaded on c# side. I don't know if it's the best way, but I solved it like this:
var weight = (((Excel.Range)sheet.Cells[row, 3]).Value);
if (weight is double)
{
product.Weight = ((double)((Excel.Range)sheet.Cells[row, 3]).Value).ToString();
}
else if (weight is string)
{
product.Weight = ((Excel.Range)sheet.Cells[row, 3]).Value;
}
I managed to read from an Excel file using IExcelDataReader, now I wish to write to specific cells in an existing Excel file, so I need to specify path to the file, column and row where the data should be inserted. I googled and found some examples but there were disputes whether the solutions worked or not. So which is the simplest way of doing this (code examples appriciated). Thanks.
Edit: So I tried doing this:
Excel.Application ExcelObj = new Excel.Application();
Excel.Workbook theWorkbook = ExcelObj.Workbooks.Open("Path", 0, true, 5,"", "", true, Excel.xlWindows, "\t", false, false,0, true);
But get the type or namespace name "Application" does not exist in the namespace Excel.
And the same for "Workbook".
I added the references Microsoft.Office.Interop.Excel and Office. What more do I need?
Using the following should sort out your namespace issues:
using Excel = Microsoft.Office.Interop.Excel;
To write to a cell you can use the following (assuming you already have a Worksheet object):
xlWorksheet.Cells["1", "A"] = "Foo";
This is the method I've been using for a couple of years and it's worked without fail every time.
You can also try doing this using some rpa tool such as G1ANT.
It will make your work much easy.
Try this simple code for updating cell:
addon xlsx version 4.101.0.0
addon core version 4.101.0.0
addon language version 4.103.0.0
xlsx.open C:\Documents\TestBook.xlsx createifnotexist true
xlsx.setvalue value 123 row 1 colname a
xlsx.close
So the company I'm working for is looking for a means to verify that a given .xls/.xlsx file is valid. Which means checking columns and rows and other data. He's having me evaluate GrapeCity Spread and SpreadsheetGear, but I'm wondering if anyone else has any other suggestions of external tools to check out.
We don't need a means to export .xls files or anything like that, just the ability to import them and verify they are valid based on a set of criteria I create.
Thanks.
If you need just to compare cell values you can use ADO.NET driver, for anything else will be required Excel or third party component. I am using SpreadsheetGear. When I was evaluating this component 3 years ago I have found an issue with conditional formatting for cell with absolute reference, but issue was quickly resolved. They have same day support response.
To my mind, the easiest way to handle this is to use an ODBC Excel data provider. I find it more straightforward to work with than the PIAs.
// Connection string for Excel 2007 (.xlsx)
string dbConnStr = #"Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};Dsn=Excel Files;dbq=C:\temp\mySpreadsheet.xlsx";
// Connection string for Excel 98-2003 (.xls)
//string dbConnStr = #"Driver={Microsoft Excel Driver (*.xls)};driverid=790;dbq=C:\temp\mySpreadsheet.xls;defaultdir=c:\temp";
OdbcCommand cmd = new OdbcCommand("Select * from [SheetName$]", new OdbcConnection(dbConnStr));
cmd.Connection.Open();
OdbcDataReader dr = cmd.ExecuteReader();
foreach (System.Data.IDataRecord item in dr)
{
// Check specific column values, etc
string id = item["Column Name"].ToString();
}
You can use the Microsoft.Office.Interop.Excel library to access any workbook the same way you do in Excel VBA.
Code looks like this:
using Excel = Microsoft.Office.Interop.Excel;
Excel.Application excel = new Excel.Application();
Excel.Workbook workbook = excel.Workbooks.Open("datasheet.xls");
Excel.Worksheet worksheet = workbook["Sheet1"] as Excel.Worksheet;
string someData = (worksheet.Range["A2"] as Excel.Range).Value.ToString();
worksheet = null;
workbook.Close();
excel.Quit();
Depending on your budget, the Aspose libraries are great. Not cheap but work very, very well.
you can use the oleDb from Microsoft to access the excel data as any other database system. You can get the right connection string from connectionstrings
Maybe the NPOI project can be useful (I have never used it though).
Best
Check out Excel Data Reader GitHub (formerly on CodePlex). I've used this a few times and it works well.
Be warned however that there are bugs reading .xlsx files where cells are skipped. Apply this patch (link is to Codeplex and out of date) I submitted for v2.0.1.0 to fix the problem. (The project maintainers don't seem active and I've had problems contacting them.)