New Comment on "How do I deliver an Excel file in ASP.NET?"
New Comment on "Pivot Table example"
New Post: formatting currency and negatives
Created Unassigned: Input string not in correct format when reading dates [9295]
I'm trying to read the data on the file attached, specifically, the two dates.
I've tried all approaches, using GetDateTime(), GetValue(), inspecting the cell, GetValue<int>(), they all fail with an exception thrown when internally attempting to parse the value as a Double.
The odd thing is that this happens whenever the file is edited with Microsoft Excel, or Kingsoft's version. But it can be fixed using LibreOffice, by selecting those two cells, changing the format to Number, and then setting the format back to Date. However, that is obviously not an option since these files are uploaded directly into a system by end user, a manual fix is out of the question.
Now, while inspecting the cell, it is identified as a DateTime cell, however the RichTextValue is shown incorrectly, as 00/25/14 for some reason, instead of actually extracting the correct date.
I've looked at the raw xml contents of the cell, which is the following:
<c r="B1" s="2"><v>41723</v></c>
The only difference I've noticed between the Excel version and the LibreOffice version, is that the LibreOffice one seems to include the "t" parameter, specifying the type as number:
<c r="B1" s="2" t="n"><v>41723</v></c>
New Post: How can I set tooltip for the cell? Is it possible?
EDIT :
My bad, I wanted to add a comment.
https://closedxml.codeplex.com/discussions/244795
New Post: Validation of cell using fixed List of values

In ClosedXML I did not find a way. I tried:
workSheet.Cell(rowIndex, 1).DataValidation.InCellDropdown= true;
workSheet.Cell(rowIndex, 1).DataValidation.AllowedValues = XLAllowedValues.List;
workSheet.Cell(rowIndex, 1).DataValidation.IgnoreBlanks = true;
workSheet.Cell(rowIndex, 1).DataValidation.Value = "yes;no";
what am I missing?New Post: Copying range become very slow than copying with Microsoft Interop Service
We have a requirement in our project where we are needed to generate reports in EXCEl with huge records.
We mainly concentrate on visualization and speed of report generation.
1.Styling cells(color,bold etc),copying formats( formulas and formats,esp number and date formats)
2.Copying ranges many times.
-
Inserting page breaks.
But I was trying to copy the range in selecting range where my range should be copied.
It was taking more and more time and slower than the Microsoft interp.
Below is the process how I'm doing
var WorkBook = LoadWorkBook();
var worksheetTest = WorkBook.Worksheet(5);
var worksheet1 = WorkBook.Worksheet(1);
var worksheet2 = WorkBook.Worksheet(2);
var worksheet3 = WorkBook.Worksheet(3);
var worksheet4 = WorkBook.Worksheet(4);
var worksheet6 = WorkBook.Worksheet(6);
var worksheet7 = WorkBook.Worksheet(7);
worksheet1.Delete();
worksheet2.Delete();
worksheet3.Delete();
worksheet4.Delete();
worksheet6.Delete();
worksheet7.Delete();
var rangeTocpy=worksheetTest.Range("a" + Convert.ToString(1), "r" + Convert.ToString(12));
var rangeDestination= worksheetTest.Range("a" + Convert.ToString(1), "r" + Convert.ToString(count + 12));
for (int i = 0; i < 500; i++)
{
rangeTocpy.CopyTo(rangeDestination);
worksheetTest.Cell(count +3, 1).Value ="Row Number"+(i+1);
count += 13;
rangeDestination= worksheetTest.Range("a" + Convert.ToString(count), "r" + Convert.ToString(count + 12));
}
WorkBook.SaveAs(ReportSaveLocaiton);
Please correct me If the way I'm trying is not so effective.Currently im using latest version :0.69.1.0 downloaded from this site.
Please update me ASAP.
New Post: Adding images to worksheet
I will have some resources to work on this if anything needs to be reworked before it gets merged.
Closed Issue: Unable to cast object of type 'ClosedXML.Excel.XLFont' to type 'ClosedXML.Excel.XLStyle' [9260]
###The Background
I'm in a bit of a high pressure situation (so sorry if I'm short in this message) and trying to figure out something with the ClosedXML library.
We have an invoice processor that opens an invoice, and uses various validators to check items.
__Most of the time, these rows process fine and I receive successful results.__ However, whenever there's a validation error at the row level (e.g. "this field is supposed to be a date but you entered a non-date", we throw a fluent validation exception with the error message to pass back to the caller (this runs in a WebAPI).
What I can't understand is that, I have the validation error and I'm ready to pass it back, and I can follow the stack trace and see exactly that error message. However, somewhere at the last second, some other exception comes up that says:
>Unable to cast object of type 'ClosedXML.Excel.XLFont' to type 'ClosedXML.Excel.XLStyle'.
I'm hoping to determine how to trap this error, as I've already received the information I receive correctly and just wish to pass back the value I already have.
**I know this is likely something that I'm doing dumb, so please feel free to point out things that you might think I've already checked.**
###Theories
It appears that something may still be hanging around in memory or trying to process, as the error occurs when serializing my final object to JSON, despite the object itself being a purely business object and having nothing to do with the Excel file.
FYI, I have tried this with spreadsheets that are completely blank, spreadsheets with the formatting removed, etc. etc. -- there should be neither fonts nor styles in these workbooks and yet I get an error about the conversion.
##The Code
I'll attempt to explain what we're doing with some code below.
In our `/api/StandardInvoiceDetailsFile` controller, where users submit the file, we:
Save the file:
```C#
var path = HostingEnvironment.MapPath(string.Format("~/App_Data/import/{0}.xlsx", DateTime.Now.Ticks));
Debug.Assert(path != null, "path != null");
file.SaveAs(path);
```
then we start the processing:
```C#
//the happy path -- process a file and return an HttpResponseMessage with the appropriate information.
try
{
IList<IStandardInvoiceDetailItem> processResult;
workbook = new XLWorkbook(path);
processResult =
new InvoiceProcessorFactory(this._clientSiteID, this._firmID).GetInvoiceProcessorInstance()
.ProcessInvoice(workbook);
}
//uh-oh, their workbook items were invalid in some way. Format and return an http OK but with a collection of validation errors and error messages.
catch (FluentValidationException validationEx)
{
workbook.Dispose();
var validationErrors = validationEx.Data["ValidationErrors"] as IList<ValidationFailure>;
return this.CreateResult(false, validationEx.Message, HttpStatusCode.OK, new List<IStandardInvoiceDetailItem>(), validationErrors.ToList());
}
```
This first step gets an invoice processor based on a client site ID and then processes the workbook that is passed in (a ClosedXML XLWorkbook in memory.)
The part where the is actually processed is below, the "ProcessInvoice" method of the invoice processor:
```C#
public IList<IStandardInvoiceDetailItem> ProcessInvoice(IXLWorkbook workbookToValidate)
{
if (workbookToValidate == null) {throw new ArgumentNullException("workbookToValidate");}
_workbookToValidate = workbookToValidate;
this.ValidateWorkbook();
this.ValidateWorksheet();
_invoiceDetailItems = this.ValidateRowsAndReturnBusinessObjects();
this.ValidateBusinessObjects(_invoiceDetailItems);
// If all's well, return the business objects.
return _invoiceDetailItems;
}
```
The exception is initially raised (correctly) in `this.ValidateRowsAndReturnBusinessObjects()`, which does the following:
```C#
var invoiceDetailItems = new List<IStandardInvoiceDetailItem>();
foreach (var row in this._workbookToValidate.Worksheet(1).RowsUsed())
{
// we don't need to worry about the header columns, hence row > 1
if (row.RowNumber() > 1 && !row.IsEmpty())
{
var rowResult = this._rowsValidator.Validate(row);
if (!rowResult.IsValid)
{
var rowValidationErrorMessage = string.Format(
"Row {0} is invalid. Validation errors:", row.RowNumber());
throw new FluentValidationException(rowValidationErrorMessage, rowResult.Errors);
}
try
{
var newItem = new StandardInvoiceDetailRow()
{
ClaimantName = row.Cell("A").GetValue<string>(),
ClaimantId = row.Cell("B").GetValue<int>(),
Matter = row.Cell("C").GetValue<string>(),
InvoiceDate = row.Cell("D").GetValue<DateTime>(),
InvoiceNumber = row.Cell("E").GetValue<string>(),
Fees = row.Cell("F").GetValue<decimal>(),
Costs = row.Cell("G").GetValue<decimal>(),
Adjustments = row.Cell("H").GetValue<decimal>(),
Total = row.Cell("I").GetValue<decimal>()
};
invoiceDetailItems.Add(newItem);
}
catch (Exception e)
{
throw new Exception("An exception occurred while trying to creatre a business object from an excel row.", e);
}
}
}
return invoiceDetailItems;
}
```
The `RowsValidator` uses FluentValidation to do the following:
```C#
public class InvoiceDetailsWorksheetRowValidator : AbstractValidator<IXLRow>, IRowsValidator
{
public InvoiceDetailsWorksheetRowValidator()
{
this.RuleFor(x => x.Cell("B"))
.Must(ExcelValidationHelpers.BeAnInt).WithMessage("ClaimantID column value is not a valid number.")
.OverridePropertyName("ClaimantIDColumn");
this.RuleFor(x => x.Cell("D"))
.Must(ExcelValidationHelpers.BeADate).WithMessage("InvoiceDate column value is not a valid date.")
.OverridePropertyName("InvoiceDateColumn");
this.RuleFor(x => x.Cell("F"))
.Must(ExcelValidationHelpers.BeADecimal).WithMessage("Fees column value is not a valid decimal.")
.OverridePropertyName("FeesColumn");
this.RuleFor(x => x.Cell("G"))
.Must(ExcelValidationHelpers.BeADecimal).WithMessage("Costs column value is not a valid decimal.")
.OverridePropertyName("CostsColumn");
this.RuleFor(x => x.Cell("H"))
.Must(ExcelValidationHelpers.BeADecimal).WithMessage("Adjustments column value is not a valid decimal.")
.OverridePropertyName("AdjustmentsColumn");
this.RuleFor(x => x.Cell("I"))
.Must(ExcelValidationHelpers.BeADecimal).WithMessage("Total column value is not a valid decimal.")
.OverridePropertyName("TotalColumn");
}
}
```
My Excel Validation helpers are as follows:
```C#
public static bool BeADecimal(IXLCell cellToCheck)
{
try
{
// ReSharper disable UnusedVariable -- this is OK; the value will never be used in this case but needs to be assigned.
var test = cellToCheck.GetValue<decimal>();
// ReSharper restore UnusedVariable
return true;
}
catch (Exception)
{
return false;
}
}
public static bool BeADate(IXLCell cellToCheck)
{
try
{
// ReSharper disable UnusedVariable -- this is OK; the value will never be used in this case but needs to be assigned.
var test = cellToCheck.GetValue<DateTime>();
// ReSharper restore UnusedVariable
return true;
}
catch (Exception)
{
return false;
}
}
public static bool BeALong(IXLCell cellToCheck)
{
try
{
// ReSharper disable UnusedVariable -- this is OK; the value will never be used in this case but needs to be assigned.
var test = cellToCheck.GetValue<long>();
// ReSharper restore UnusedVariable
return true;
}
catch (Exception)
{
return false;
}
}
public static bool BeAnInt(IXLCell cellToCheck)
{
try
{
// ReSharper disable UnusedVariable -- this is OK; the value will never be used in this case but needs to be assigned.
var test = cellToCheck.GetValue<int>();
// ReSharper restore UnusedVariable
return true;
}
catch (Exception)
{
return false;
}
}
}
```
##I know it's a lot -- please ask questions!
The complicated nature of the code means it's tough for me to succinctly show the problem, especially since it involves an exception that I can't (yet) trap or trace in any way. I will do my best to rip this code out and get it into an exe of some kind that can be studied. I am happy to answer any questions you may have.
Comments: This issue ended up being something else. Will be posting a new issue for clarity (and a patch from a coworker -- his first contribution to ClosedXML).
Created Unassigned: Certain "Equals(object obj)" methods cast without checking type first [9310]
```csharp
public override bool Equals(object obj)
{
return Equals((XLStyle)obj);
}
```
this assumes that any object is definitely an `XLStyle` at this point, which may not be the case. (In our instance, it appears to be checking a XLFont object). Regardless, defense programming would suggest the need to be a little more cautious rather than directly casting.
In this case, we'd expect want any object that isn't an XLStyle (or at least that implements IXLStyle) to return false, and otherwise go into the comparison.
We'll submit a patch to fix this in a few areas and will test it in our application to see if it resolves the issue first. Essentially, it would insert a guard clause, e.g. `if (!obj is IXLStyle){ return false; }` to ensure that the casting issue doesn't happen.
Interested in thoughts, but this seems pretty straightforward at first glance.
New Post: Using foreach to deal with Excel rows...
var wb = new XLWorkbook(Filename);
var ws = wb.Worksheets.First();
var range = ws.RangeUsed();
foreach(var row in range.Rows())
{
}
The problem is there isn't such overload for Rows(). All overloads require parameters.Error 1 No overload for method 'Rows' takes '0' arguments
How can I use foreach to deal with the excel rows?
Thanks
Created Unassigned: Crashes on XLWorkbook workbook = new XLWorkbook(); [9314]
Attached is a picture of the error
Commented Unassigned: Crashes on XLWorkbook workbook = new XLWorkbook(); [9314]
Attached is a picture of the error
Comments: ** Comment from web user: orangeman1990 **
aaand I didn't want to submit yet. I'm tired, it's 12:40am and I've been at this for a couple of hours. Here is my code:
```
[HttpPost]
public ActionResult ExportExcel()
{
var workbook = new XLWorkbook();
workbook.Worksheets.Add("Sample").Cell(1, 1).SetValue("Hello World");
// Prepare the response
Response.Clear();
Response.ContentType = "application/vnd.ms-excel";
Response.AddHeader("content-disposition", "attachment;filename=\"HelloWorld.xlsx\"");
// Flush the workbook to the Response.OutputStream
MemoryStream memoryStream = new MemoryStream();
workbook.SaveAs(memoryStream);
memoryStream.WriteTo(Response.OutputStream);
memoryStream.Close();
Response.End();
return RedirectToAction("KPIExport");
}
```
Commented Unassigned: Crashes on XLWorkbook workbook = new XLWorkbook(); [9314]
Attached is a picture of the error
Comments: ** Comment from web user: metalrose **
Have you referenced the OpenXML DLL ? This needs to be referenced as well as ClosedXML.
Available here:
[TEXT](https://www.codeplex.com/Download?ProjectName=closedxml&DownloadId=177539)
New Post: Closing a ClosedXML generated Workbook.
I have the following code:
Private Sub Btn_export_Click() Handles Btn_export.Click
Dim book As XLWorkbook = New XLWorkbook(XLEventTracking.Disabled)
Dim table As System.Data.DataTable
table = DGV_preview.DataSource
book.AddWorksheet(table, "Result")
book.SaveAs("visitation.xlsx")
' HERE BE SOME E-MAIL SENDING
book.Worksheets(0).Dispose()
book.Dispose()
table.Dispose()
File.Delete("visitation.xlsx")
End Sub
Basically I want to create an Excel file, transfer a DataTable into it, Save the file, e-mail it and then delete the file. Everything works perfectly until I want to delete the file. How on earth do I close the file so I can delete it? I can't seem to find the way to do it. :(
Thank you VERY much for this amazing work you've done, by the way.
New Post: Using foreach to deal with Excel rows and skip the 1st row as header
There are 3 overloads
- IXLRangeRows Rows(Func<IXLRangeRow, bool> predicate = null); // but this could be empty!
- IXLRangeRows Rows(string rows); // e.g. Rows("4:5"), Rows("7:8,10:11"), Rows("13")
-
IXLRangeRows Rows(int firstRow, int lastRow);
string test1 = row.Field("Name").GetString(); // <--- Doesn't work
Note - this will only work if one of the columns has the heading of "Name"Do any of your columns have the heading of "Name"?
string test2 = row.Cell(1).GetString(); // <--- Works but doesn't skip header row
Of course not. You told it to iterate through all the rows!To skip the first row do
foreach(var row in table.Rows(table.FirstRow+1,table.LastRow))
New Post: Using foreach to deal with Excel rows and skip the 1st row as header
IXLRangeRows Rows(Func<IXLRangeRow, bool> predicate = null); // but this could be empty!
It doesn't work in my case, I have tried to use Rows() without arguments but the compiler fails.Regarding
string test1 = row.Field("Name").GetString();
I surely have a column called "Name" but since the Rows() doesn't work I cannot test it.According to the article and since the current row is set, I could get the data from Field("Name") without the need to skip the header row.
New Post: Using foreach to deal with Excel rows and skip the 1st row as header
foreach (var row in table.DataRange.Rows()) // DataRange skips the headers
{
var name = row.Field("Name").GetString();
}
Hope this helps.Commented Unassigned: Crashes on XLWorkbook workbook = new XLWorkbook(); [9314]
Attached is a picture of the error
Comments: ** Comment from web user: roberttanenbaum **
At the very top of the Documentation page [https://closedxml.codeplex.com/documentation](https://closedxml.codeplex.com/documentation) it says
__Requirements:
To use ClosedXML you must reference the following DLL: DocumentFormat.OpenXml.dll (part of MS Open XML SDK 2.0)__
After it is downloaded you have to add it to the References section of the Visual Studio project
New Post: Closing a ClosedXML generated Workbook.
First try getting rid of all those .Dispose(), they're not doing anything in your case.
If that doesn't work you could try putting the workbook/file creation and the file delete in two different functions, then call both from the click event.