I’m using Codeplex Excel Data Reader to read an excel. The problem that I face is It reads Excel 97-2003 documents without any difficulty, but when reading Excel 207-2010 documents using ExcelReaderFactory.CreateOpenXmlReader(stream), it output’s an empty data set. Did anyone faced this problem. And is any one has any solution for this?
The read method is as follows
private DataSet ReadExcel(string fileName, string extention)
{
DataSet dsData = null;
FileStream stream = File.Open(fileName, FileMode.Open, FileAccess.Read);
IExcelDataReader excelReader = null;
try
{
if (extention.Equals("xls"))
{
//1. Reading from a binary Excel file ('97-2003 format; *.xls)
excelReader = ExcelReaderFactory.CreateBinaryReader(stream);
}
else
{
//2. Reading from a OpenXml Excel file (2007 format; *.xlsx)
excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
// excelReader = ExcelReaderFactory.CreateBinaryReader(stream);
}
excelReader.IsFirstRowAsColumnNames = false;
dsData = excelReader.AsDataSet();
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (excelReader != null)
{
excelReader.Close();
}
}
return dsData;
}
8000401a indicates it was something to do with Run As Logon Failure.
Steer clear of server-side automation of office. Or use XML to work with Excel spreadsheets on the server.
According to the support issues with the Excel Data Reader:
Design and usage are great. So far only issue I've had is with certain
XLSX file not parsing correctly (reading in wrong sheets, missind cell
values, etc). To resolve these issues, I had to rebuild Excel.dll
using latest SharpZipLib from
http://www.icsharpcode.net/OpenSource/SharpZipLib/Download.aspx. As
others have said, project needs an update, but is still good.
Or just use the standard micrsoft way:
Microsoft.Office.Interop.Excel.Application xlApp;
Workbook wb = null;
try
{
wb = xlApp.Workbooks.Open(filePath, false, true,5,null,"WrongPAssword");
}
foreach (object possibleSheet in wb.Sheets)
{
var aSheet = possibleSheet as Worksheet;
if (aSheet != null)
{
....
Related
I have come across two spreadsheets giving me errors when using Open XML SDK to convert.
The cases are:
Read-only password protection (I don't have password)
Filesharing enabled (another user on the network has the spreadsheet open and spreadsheet is read-only until user closes spreadsheet)
If I use Excel Interop, it is possible to give parameters that will open a copy of the spreadsheet and enable write permissions and hence any programmatic conversion process can continue. This code enables the behaviour by utilising IgnoreReadOnlyRecommended
// Convert legacy Excel files to .xlsx Transitional using Microsoft Office Interop Excel
public bool Convert_Legacy_ExcelInterop(string input_filepath, string output_filepath)
{
bool convert_success = false;
// Open Excel
Excel.Application app = new Excel.Application(); // Create Excel object instance
app.DisplayAlerts = false; // Don't display any Excel prompts
Excel.Workbook wb = app.Workbooks.Open(input_filepath, ReadOnly: false, Password: "'", WriteResPassword: "'", IgnoreReadOnlyRecommended: true, Notify: false); // Create workbook instance
// Save workbook as .xlsx Transitional and close Excel
wb.SaveAs(output_filepath, 51);
wb.Close();
app.Quit();
return convert_success = true;
}
How can I imitate the same behaviour using Open XML SDK?
Here's my code:
// Convert to .xlsx Transitional
public bool Convert_to_OOXML_Transitional(string input_filepath, string output_filepath)
{
bool convert_success = false;
// If write-protected or reserved by another user
using (SpreadsheetDocument spreadsheet = SpreadsheetDocument.Open(input_filepath, false))
{
if (spreadsheet.WorkbookPart.Workbook.WorkbookProtection != null || spreadsheet.WorkbookPart.Workbook.FileSharing != null)
{
// Use Excel Interop to convert the spreadsheet
Convert_Legacy_ExcelInterop(input_filepath, output_filepath);
return convert_success = true;
// REPLACE ABOVE CODE WITH SOMETHING NATIVE TO OPEN XML SDK
}
}
// Convert spreadsheet
byte[] byteArray = File.ReadAllBytes(input_filepath);
using (MemoryStream stream = new MemoryStream())
{
stream.Write(byteArray, 0, (int)byteArray.Length);
using (SpreadsheetDocument spreadsheet = SpreadsheetDocument.Open(stream, true))
{
spreadsheet.ChangeDocumentType(SpreadsheetDocumentType.Workbook);
}
File.WriteAllBytes(output_filepath, stream.ToArray());
}
// Repair spreadsheet
Repair rep = new Repair();
rep.Repair_OOXML(output_filepath);
// Return success
convert_success = true;
return convert_success;
}
is there a way to export information to an xlsm file? the steps I do is:
in a button I put an input to select the file, I upload the file to the server
I look for the sheet which is already specified in the code
I modify the file information according to the information to be exported
command to save the file locally.
the error is as follows:
{"The 'br' start tag on line 59 position 30 does not match the end tag of 'font'. Line 60, position 9."}
when indicating the sheet with which to work
I share my code: any suggestions?
public void ExportFile(string FileName, string UserID)
{
FileInfo fi = new FileInfo(FileName);
Master.MSGError = string.Empty;
string SheetName = "test";
using (MemoryStream file = new MemoryStream())
{
try
{
using (ExcelPackage xlPackage = new ExcelPackage(fi))
{
ExcelWorksheet worksheet;
worksheet = xlPackage.Workbook.Worksheets[SheetName]; //here is the error exception
worksheet.Cells[1, 1].Value = "TEST";
//save file
xlPackage.SaveAs(file);
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.BinaryWrite(file.ToArray());
Response.Flush();
Response.End();
}
}
catch (Exception ex)
{
Master.fc.MSGError = ex.Message;
}
}
}
Currently I solved my problem I thought that the detail was in the macro, but I found the real error doing different tests, it seems that both epplus and closedxml have problems reading certain information in the excel, I ended up using closedxml and applying the solution:
OpenXml Excel: throw error in any word after mail address
I'm sorry for confusion
I have a XSLT transformed HTML data in MemoryStream (in C#). I am trying to convert this to an Excel format before emailing, preferably conversion happens all in memory again without saving to local disk. I can worry about the email attachment part later. Can anyone point me to a sample on how I could do the conversion from HTML to Excel format either through OpenXML or with Office.Interop.Excel.
The HTML data is well formed and I could manually do the conversion by opening the html in Excel application and do a Save As to save it in xlsx format (Office 2010), no problem. I also tried to simply change the .html extension to .xlsx, but then excel complains about opening it.
What's the best way to automate the manual SaveAs action so that I could use the same html data in Excel format? I understand that I could create a separate .xslt for directly converting my XML into Excel format. But, that'll be too many .xslt to maintain. I'm trying to find the hack to let Excel do the work for me.
Thank you for any and all pointers in advance!
EDIT:
I figured I have no choice but to store html to disk and read it back and use Excel Interop to do SaveAs method. When I did try though, getting the exception with HRESULT: 0x800A03EC on the SaveAs method. Here's how to reproduce it.
steps to reproduce the behavior
Save this text
<html><head></head><body><center><h1>Test Header</h1></center></body></html>
as C:\Test.html
after making reference to Excel interop like this,
using Excel = Microsoft.Office.Interop.Excel;
Try this code
`
var app = new Excel.Application();
Excel.Workbook wb = null;
try
{
wb = app.Workbooks.Open(#"c:\test.html");
wb.SaveAs(#"c:\test.xlsx", Excel.XlFileFormat.xlOpenDocumentSpreadsheet);
//wb.SaveCopyAs(#"c:\test.xlsx");
wb.Close();
}
catch (Exception ex)
{
//_logger.Error(ex);
}
finally
{
app.Quit();
}
`
I always get the mentioned exception on SaveAs no matter which fileformat I choose or even not mentioning the fileformat there..
Any ideas?
This code works. It turns out the exception I was getting is only related to the file format I was trying to save. When I changed it to Open XML workbook, it saved fine.
using Excel = Microsoft.Office.Interop.Excel;
.
.
.
var app = new Excel.Application();
Excel.Workbook wb = null;
try
{
wb = app.Workbooks.Open(#"c:\test.html");
wb.SaveAs(#"c:\test.xlsx", Excel.XlFileFormat.xlOpenXMLWorkbook);
//wb.SaveCopyAs(#"c:\test.xlsx");
wb.Close();
}
catch (Exception ex)
{
//_logger.Error(ex);
}
finally
{
app.Quit();
}
Here's the updated code that takes bytes[] html as input and returns xlsx in bytes[]
public static byte[] DoConvertXlDataToOpenXml(byte[] data, FileInfo fileInfo)
{
ExcelInterop.Application excelApp = null;
ExcelInterop.Workbooks workBooks = null;
ExcelInterop.Workbook workBook = null;
FileInfo tempFile = null;
FileInfo convertedTempFile = null;
try
{
//Stream the file to temporary location, overwrite if exists
tempFile = new FileInfo(Path.ChangeExtension(Path.Combine(Path.GetTempFileName()), fileInfo.Extension));
using (var destStream = new FileStream(tempFile.FullName, FileMode.Create, FileAccess.Write))
{
destStream.Write(data, 0, data.Length);
}
//open original
excelApp = new ExcelInterop.Application();
excelApp.Visible = false;
excelApp.DisplayAlerts = false;
workBooks = excelApp.Workbooks;
workBook = workBooks.Open(tempFile.FullName);
convertedTempFile = new FileInfo(Path.ChangeExtension(Path.GetTempFileName(), "XLSX"));
//Save as XLSX
excelApp.Application.ActiveWorkbook.SaveAs(
convertedTempFile.FullName
, Microsoft.Office.Interop.Excel.XlFileFormat.xlOpenXMLWorkbook
, ConflictResolution: ExcelInterop.XlSaveConflictResolution.xlLocalSessionChanges);
excelApp.Application.ActiveWorkbook.Close();
return File.ReadAllBytes(convertedTempFile.FullName);
}
catch (Exception)
{
throw;
}
finally
{
if (workBooks != null)
Marshal.ReleaseComObject(workBooks);
if (workBook != null)
Marshal.ReleaseComObject(workBook);
if (excelApp != null)
Marshal.ReleaseComObject(excelApp);
if (tempFile != null && tempFile.Exists)
tempFile.Delete();
if (convertedTempFile != null && convertedTempFile.Exists)
{
convertedTempFile.Delete();
}
}
}
I am trying to read a sheet data from excel (tried both oldedb and odbc) and found out that there is 255 characters limit.
I tried using Range object as suggested in other threads
(SELECT * FROM [ref_MethodInput$A1:S362])
but still no luck. So apart from using interop is there any other way to overcome this? Registry edit is also not advisable as that would need registry edits in all client machines.
Since the issue is with the Jet Provider, why not try the Microsoft Excel Driver listed under ODBC connctions.
Source
below code work for me.
import data from excel (.xls & .xlsx) file (work for column value more than 255 character).
using Excel;
try
{
FileStream stream = File.Open(strFilePath, FileMode.Open, FileAccess.Read);
IExcelDataReader excelReader = null;
if (extension.Trim() == ".xls")
{
excelReader = ExcelReaderFactory.CreateBinaryReader(stream);
}
else if (extension.Trim() == ".xlsx")
{
excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
}
excelReader.IsFirstRowAsColumnNames = true;
DataSet result = excelReader.AsDataSet();
excelReader.Close();
}
catch (Exception err)
{
mResult.Message = err.Message;
}
Download nuget packages:
1) PCLStorage (Version: 1.0.2)
2) ExcelDataReader-DevNet45 (version: 1.0.0.2)
Code reference
I'm using the EPPLUS library to read data from Excel to create another file. Unfortunately it does not support the .XLSM extension file. Is there a nice way to convert .XLSM files to .XLSX file for the purpose of reading the file with EPPLUS?
(using EPPLUS for reading would be nice because all my code is already written using it :) )
In order to do this you will need to use the Open XML SDK 2.0. Below is a snippet of code that worked for me when I tried it:
byte[] byteArray = File.ReadAllBytes("C:\\temp\\test.xlsm");
using (MemoryStream stream = new MemoryStream())
{
stream.Write(byteArray, 0, (int)byteArray.Length);
using (SpreadsheetDocument spreadsheetDoc = SpreadsheetDocument.Open(stream, true))
{
// Change from template type to workbook type
spreadsheetDoc.ChangeDocumentType(SpreadsheetDocumentType.Workbook);
}
File.WriteAllBytes("C:\\temp\\test.xlsx", stream.ToArray());
}
What this code does is it takes your macro enabled workbook file and opens it into a SpreadsheetDocument object. The type of this object is MacroEnabledWorkbook, but since you want it as a Workbook you call the ChangeDocumentType method to change it from a MacroEnabledWorkbook to a Workbook. This will work since the underlying XML is the same between a .xlsm and a .xlsx file.
Using the Open XML SDK, like in amurra's answer, but
in addition to changing doc type, VbaDataPart and VbaProjectPart should be removed, otherwise Excel will show error a file is corrupted.
using (var inputStream = File.OpenRead("C:\\temp\\test.xlsm"))
using (var outStream = new MemoryStream()) {
inputStream.CopyTo(outStream);
using (var doc = SpreadsheetDocument.Open(outStream, true)) {
doc.DeletePartsRecursivelyOfType<VbaDataPart>();
doc.DeletePartsRecursivelyOfType<VbaProjectPart>();
doc.ChangeDocumentType(DocumentFormat.OpenXml.SpreadsheetDocumentType.Workbook);
}
File.WriteAllBytes("C:\\temp\\test.xlsx", outStream.ToArray());
}
package xlsbtoxlsx;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.regex.Pattern;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbookType;
public class XlsbToXlsxConvertor {
public static void main(String[] args) throws Exception {
String inputpath="C:\\Excel Data Files\\XLSB\\CSD_TDR_20200823";
String outputpath="C:\\Excel Data Files\\XLSB\\output";
new XlsbToXlsxConvertor().xlsmToxlsxFileConvertor(inputpath, outputpath);
}
public void xlsmToxlsxFileConvertor(String inputpath, String outputpath) throws Exception {
XSSFWorkbook workbook;
FileOutputStream out;
System.out.println("inputpath " + inputpath);
File directoryPath = new File(inputpath);
// List of all files and directories
String contents[] = directoryPath.list();
System.out.println("List of files and directories in the specified directory:");
for (int i = 0; i < contents.length; i++) {
System.out.println(contents[i]);
// create workbook from XLSM template
workbook = (XSSFWorkbook) WorkbookFactory
.create(new FileInputStream(inputpath + File.separator + contents[i]));
// save copy as XLSX ----------------START
OPCPackage opcpackage = workbook.getPackage();
// get and remove the vbaProject.bin part from the package
PackagePart vbapart = opcpackage.getPartsByName(Pattern.compile("/xl/vbaProject.bin")).get(0);
opcpackage.removePart(vbapart);
// get and remove the relationship to the removed vbaProject.bin part from the
// package
PackagePart wbpart = workbook.getPackagePart();
PackageRelationshipCollection wbrelcollection = wbpart
.getRelationshipsByType("http://schemas.microsoft.com/office/2006/relationships/vbaProject");
for (PackageRelationship relship : wbrelcollection) {
wbpart.removeRelationship(relship.getId());
}
// set content type to XLSX
workbook.setWorkbookType(XSSFWorkbookType.XLSX);
// write out the XLSX
out = new FileOutputStream(outputpath + File.separator + contents[i].replace(".xlsm", "") + ".xlsx");
workbook.write(out);
out.close();
System.out.println("done");
workbook.close();
}
}
}