Is Apache POI support modify password protect xlsx file content? - apache-poi

After I generate a password protected xlsx file with apache poi, I modify file content with XSSFWorkbook.like:
File file = new File("Test2.xlsx");
XSSFWorkbook wb = (XSSFWorkbook) WorkbookFactory.create(file, "password");
wb.createSheet("Test0001");
try (FileOutputStream fileOutputStream = new FileOutputStream(file)) {
wb.write(fileOutputStream);
} finally {
wb.close();
}
when I reopen the file, the file was no longer password protected,Apache POI and poi-ooxml version:5.2.1.Maybe poi not support modify password protected xlsx file?
is there anyway modify password protected xlsx file with apache poi?

Related

Documents4j java library in Android App to convert Docx to Pdf

I am trying to use Documents4j java library in my Android App to convert Docx format document to PDF file but the output pdf file is damaged or corrupted.
The output pdf file is empty with 0 bytes.
I am using the below code to convert Docx to pdf.
String uniqueString = UUID.randomUUID().toString();
File outputFile = new File(Environment.getExternalStorageDirectory() + "/meer_" + uniqueString+".pdf");
File inputWord = new File(input);
try {
InputStream docxInputStream = new FileInputStream(inputWord);
OutputStream outputStream = new FileOutputStream(outputFile);
IConverter converter = LocalConverter.builder().build();
converter.convert(docxInputStream).as(DocumentType.DOCX).to(outputStream).as(DocumentType.PDF).execute();
outputStream.close();
System.out.println("success");
} catch (Exception e) {
e.printStackTrace();
}
if(outputFile.exists()){
openPdf(outputFile);
}
documents4j functions by delegating the conversion from the Java application to an instance of MS Word. This instance can run on a server which you can reach via HTTP(S) but the local converter will of course not work on Android which is unable to run MS Word.

Excel OpenXML, OleDB and "External table is not in the expected format" error

I am generating Excel files using OpenXML, the file opens without any issues on my desktop with Excel 2016 installed. The file also passes validation using Open XML Productivity Tool 2.5.
The problem is that the file is rejected from the SQL Server Integration Services (SSIS) processing. The error is "External table is not in the expected format"
As far as I know SSIS is using OLEDB to process the files.
I have tried to read the file locally using the following code and was able to reproduce the same error.
The code is as follows:
var fileName = "C:\\Temp\\myExcel.xlsx";
var connectionString = String.Empty;
if (Path.GetExtension(fileName) == ".xlsx")
{
connectionString = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"Excel 12.0;HDR=YES;\"", fileName);
}
else //.xls
{
connectionString = string.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties=\"Excel 8.0;HDR=YES;IMEX=1;\"", fileName);
}
using (OleDbConnection conn = new OleDbConnection(connectionString))
{
conn.Open();
var adapter = new OleDbDataAdapter("select * from [test$]", conn);
var excelDataSet = new DataSet();
adapter.Fill(excelDataSet, "anyNameHere");
var data = excelDataSet.Tables["anyNameHere"];
foreach (DataRow row in data.Rows)
{
Console.Out.WriteLine(row[NAME].ToString());
}
}
All I was able to find in the net that this error is due to wrong connection string (Microsoft.Jet.OLEDB.4.0 and Excel 8.0 instead of Microsoft.ACE.OLEDB.12.0 and Excel 12.0) but I already have this.
This is definitely something wring with the file itself. The problem disappears if I open the file in Excel, and use save as.
I was trying to unpack the original and resaved files and compare the contents but the difference is huge, when saving excel adds lots of styles, themes, and xmls references. I really would not like to follow that path.
Do you know what parts are important for OleDB provider when reading Excel??

Exporting XLSX file with Epplus generates file with error

Problem
I'm trying to send a List to an Excel file by using the LoadFromCollection method.
After I generate an XLSX file, it does not open but if I change the extension to XLS, it appears like this.
ExcelFileError
Code
[HttpGet]
[Route("GetExcel")]
public async Task<HttpResponse> GetExcel()
{
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.ClearContent();
HttpContext.Current.Response.ClearHeaders();
HttpContext.Current.Response.Buffer = true;
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
var stream = new MemoryStream();
using (var excelPackage = new ExcelPackage())
{
ExcelWorksheet ws = excelPackage.Workbook.Worksheets.Add("SoftwareVersao");
var result = await _versaoAppService.Selecionar();
ws.Cells["A1"].LoadFromCollection(result);
ws.Cells.AutoFitColumns();
excelPackage.SaveAs(stream);
}
HttpContext.Current.Response.BinaryWrite(stream.ToArray());
HttpContext.Current.Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
HttpContext.Current.Response.AddHeader("content-disposition", "attachment;filename=" + "SoftwareVersao.xlsx");
HttpContext.Current.Response.Flush();
HttpContext.Current.ApplicationInstance.CompleteRequest();
return HttpContext.Current.Response;
}
This code generates a corrupted XLSX file if I change the lines below it generates the above image.
HttpContext.Current.Response.ContentType = "application/vnd.ms-excel"
HttpContext.Current.Response.AddHeader("content-disposition", "attachment;filename=" + "SoftwareVersao.xls");
Attempts
I've made several attempts.
I used HttpResponseMessage instead of HttpResponse
I used a blank template in creating the file
I changed the enconding
I used several code snippets
What am I doing wrong? Is there something I forgot to implement?
Update
I found this question and now could generate the XLSX file, but I'm having the same problem that the author of the question, where Excel have to repair the file.
WebApi using EF EPPlus returning gibberish in exce

Download an excel file and read content with azure functions

I am trying to write a C# Azure Function to download and open an excel file using the OpenXml-SDK.
Office Interop doesn't work here because office is not available to the Azure Function.
I am trying to use OpenXml-SDK to open and read the file which seems to require a path to the saved file and not the url or a Stream downloaded from the remote url.
Given I don't know of a way to temporary store the excel file in Azure Functions, I used Azure File Storage.
I uploaded the excel file from the url to Azure File Storage, however I cannot open the excel file with OpenXML-SDK.
I tested the excel file in Azure File Storage is working, however, when I try to open the OpenXML.SpreadsheetDocument form a MemoryStream I get error indicating the file is corrupt.
If I try to open the SpreadsheetDocument passing the file Uri (https://learn.microsoft.com/en-us/azure/storage/storage-dotnet-how-to-use-files#develop-with-file-storage) then the address passes the 260 character limit.
I'm open to using a library other than OpenXML and ideally I would prefer not to have to store the excel file.
Open XML SDK works fine in Azure Function. I tested it on my side. Here is the full code.
#r "DocumentFormat.OpenXml.dll"
#r "WindowsBase.dll"
using System.Net;
using System.IO;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
public static HttpResponseMessage Run(HttpRequestMessage req, TraceWriter log)
{
log.Info($"C# HTTP trigger function processed a request. RequestUri={req.RequestUri}");
WebClient client = new WebClient();
byte[] buffer = client.DownloadData("http://amor-webapp-test.azurewebsites.net/Content/hello.xlsx");
MemoryStream stream = new MemoryStream();
stream.Write(buffer, 0, buffer.Length);
stream.Position = 0;
using (SpreadsheetDocument doc = SpreadsheetDocument.Open(stream, false))
{
WorkbookPart workbookPart = doc.WorkbookPart;
SharedStringTablePart sstpart = workbookPart.GetPartsOfType<SharedStringTablePart>().First();
SharedStringTable sst = sstpart.SharedStringTable;
WorksheetPart worksheetPart = workbookPart.WorksheetParts.First();
Worksheet sheet = worksheetPart.Worksheet;
var cells = sheet.Descendants<Cell>();
var rows = sheet.Descendants<Row>();
log.Info(string.Format("Row count = {0}", rows.LongCount()));
log.Info(string.Format("Cell count = {0}", cells.LongCount()));
// One way: go through each cell in the sheet
foreach (Cell cell in cells)
{
if ((cell.DataType != null) && (cell.DataType == CellValues.SharedString))
{
int ssid = int.Parse(cell.CellValue.Text);
string str = sst.ChildElements[ssid].InnerText;
log.Info(string.Format("Shared string {0}: {1}", ssid, str));
}
else if (cell.CellValue != null)
{
log.Info(string.Format("Cell contents: {0}", cell.CellValue.Text));
}
}
}
return req.CreateResponse(HttpStatusCode.OK, "Hello ");
}
To use Open XML, please make sure you have created a bin folder under your function folder and uploaded DocumentFormat.OpenXml.dll and WindowsBase.dll to it.
"File contains corrupted data".
Have you tried another excel file to check whether the issue is related to specific excel file. I suggest you create a new simple excel to test your code again.
"It didn't work on my file with the same "File contains corrupted data" message. "
I download your excel file and found that it is a older version(.xls) of excel file.
To fixed the exception, you could convert the excel to latest version(.xlsx) or choose another excel parse library. ExcelDataReader could work for any versions of excel file. You could install this library using NuGet by searching 'ExcelDataReader'. Following is the sample code of how to parse .xls format excel file. I tested it on Azure Function, it did worked fine.
#r "Excel.dll"
#r "System.Data"
using System.Net;
using System.IO;
using Excel;
using System.Data;
public static HttpResponseMessage Run(HttpRequestMessage req, TraceWriter log)
{
log.Info($"C# HTTP trigger function processed a request. RequestUri={req.RequestUri}");
WebClient client = new WebClient();
byte[] buffer = client.DownloadData("http://amor-webapp-test.azurewebsites.net/Content/abcdefg.xls");
MemoryStream stream = new MemoryStream();
stream.Write(buffer, 0, buffer.Length);
stream.Position = 0;
IExcelDataReader excelReader = ExcelReaderFactory.CreateBinaryReader(stream);
DataSet result = excelReader.AsDataSet();
for (int i = 0; i < result.Tables.Count; i++)
{
log.Info(result.Tables[i].TableName +" has " + result.Tables[i].Rows.Count + " rows.");
}
return req.CreateResponse(HttpStatusCode.OK, "Hello ");
}
Please add "Excel.dll" file to the bin folder of your function before executing upper code.
If you do need to save a temporary file, Azure Functions has a %TEMP% environment variable with a path to a temporary folder. This is a folder that is local to the vm that runs your function and will not be persisted.
However, saving the file locally / in Azure Files is unnecessary. You should be able to get the stream from the response to your get request and pass it straight to OpenXML.
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(originalExcelUrl);
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
using (Stream stream = response.GetResponseStream())
{
var doc = SpreadsheetDocument.Open(stream, true);
// etc
}

the file you are trying to open is in a different format than specified by the file extension in Asp.Net

the file you are trying to open is in a different format than specified by the file extension c# error when trying to open file in excel.
Here is my code
public ActionResult Export(string filterBy)
{
MemoryStream output = new MemoryStream();
StreamWriter writer = new StreamWriter(output, Encoding.UTF8);
var data = City.GetAll().Select(o => new
{
CountryName = o.CountryName,
StateName = o.StateName,
o.City.Name,
Title = o.City.STDCode
}).ToList();
var grid = new GridView { DataSource = data };
grid.DataBind();
var htw = new HtmlTextWriter(writer);
grid.RenderControl(htw);
writer.Flush();
output.Position = 0;
return File(output, "application/vnd.ms-excel", "test.xls");
}
when am trying to open excel i get this error
the file you are trying to open is in a different format than
specified by the file extension
After clicking on Yes the file open properly. but i don't want this msg to appear.
I have used CloseXML to solve the problem.
public static void ExportToExcel(IEnumerable<dynamic> data, string sheetName)
{
XLWorkbook wb = new XLWorkbook();
var ws = wb.Worksheets.Add(sheetName);
ws.Cell(2, 1).InsertTable(data);
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
HttpContext.Current.Response.AddHeader("content-disposition", String.Format(#"attachment;filename={0}.xlsx",sheetName.Replace(" ","_")));
using (MemoryStream memoryStream = new MemoryStream())
{
wb.SaveAs(memoryStream);
memoryStream.WriteTo(HttpContext.Current.Response.OutputStream);
memoryStream.Close();
}
HttpContext.Current.Response.End();
}
Installed ClosedXML in my project using Nuget Package Manager.
the file you are trying to open is in a different format than
specified by the file extension
You are constantly getting that warning message because the file that got created is not an actual excel file. If you will look into the generated file, it's just a bunch of html tags. Remember that a GridView's RenderControl will generate an html table.
To fix your issue, you need to either use a third party tool that creates a real excel file (one tool you might want to use is NPOI) or create a comma-delimited file, or simply a csv file, and return that file.
In case someone else stumbles across this... I needed to convert blobs back into files on-the-fly in C#. Pdf's worked well and excel gave me this same error as OP explains.
This is the code I wrote which handles excel differently from other file types.
Giving excel application/octet-stream with an actual filename solved my issue. Probably not the cleanest way to do it but it was good enough for my purposes.
string theExt = Path.GetExtension(theDoc.documentFileName).ToUpper();
Response.Clear();
if (theExt == ".XLS" || theExt == ".XLSX"){
Response.ContentType = "application/octet-stream";
Response.AddHeader("Content-Disposition", string.Format("inline; filename={0}", theDoc.documentFileName));
}
else{
Response.ContentType = theDoc.documentMimeType;
Response.AddHeader("Content-Disposition", string.Format("inline; filename={0}", theDoc.documentTitle));
}
using (MemoryStream stream = new MemoryStream(theDoc.file))
{
stream.WriteTo(Response.OutputStream);
stream.Close();
};
Response.End();
In case someone needs to export a dataset as excel file with CloseXML.
Dataset ds = { your data from db }
var xlsx = new XLWorkbook();
var dataTable = ds.Tables[0];
xlsx.Worksheets.Add(dataTable);
xlsx.SaveAs("export.xlsx");

Resources