I am having trouble swapping a file. From XLS to XLSX - c#

I'm trying to make a change in the application code, because I've tried it anyway and I'm not having success. I have a reporting tab on my system, but it is only exporting XLS files and I need to switch to XLSX because the XLS is limited to 65,000 lines. I'll show a part of my controler when he's mounting the XLS. I can not show my Service method because it is VERY large and you would be kind of lost.
[CustomAuthorize(TipoFuncao.PRINT)]
public ActionResult Index(FiltroRptManifesto filtro)
{
byte[] result = null;
bool overflowMonth = false;
IWorkbook workbook = new XSSFWorkbook();
try
{
RptManifestoService rptManifestoService = new RptManifestoService(ModelState);
result = rptManifestoService.GeraExcel(Server.MapPath("~/Content/RptManifesto.xls"), filtro, ViewBag.Usuario);
if (ModelState.IsValid)
{
if (ValidateDate(ModelState["DtProtocoloIni"].Value, ModelState["DtProtocoloFin"].Value).Days > 540)
{
overflowMonth = true;
throw new Exception();
};
Response.AppendCookie(new HttpCookie("downloadToken", filtro.DownloadToken));
return File(result, "application/vnd.ms-excel", "Manifesto.xls");
}
}
//...

I've never used NPOI so I may be wrong but what happens if you do:
var fileName = "Manifesto.xlsx";
return File(result, MimeMapping.GetMimeMapping(fileName), fileName);
or
return File(
result,
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"Manifesto.xlsx");

Related

Excel compare by byte array

I would like to achieve excel sheets comparison by comparing excels sheets transferred into byte arrays
Actually my code looks like:
public static Document FileToByteArray(string fileName)
{
System.IO.FileStream fs = new System.IO.FileStream(fileName, System.IO.FileMode.Open, System.IO.FileAccess.Read);
System.IO.BinaryReader binaryReader = new System.IO.BinaryReader(fs);
long byteLength = new System.IO.FileInfo(fileName).Length;
byte[] fileContent = binaryReader.ReadBytes((int)byteLength);
fs.Close();
fs.Dispose();
binaryReader.Close();
Document Document = new Document
{
DocContent = fileContent
};
return Document;
}
public class Document
{
public byte[] DocContent { get; set; }
}
And finally main code:
private static void CompareImportedExportedExcels(string ingredientName, string ingredientsExportFile, AuthorizedLayoutPage authorizedBackofficePage, IngredientsPage ingredientsPage)
{
authorizedBackofficePage.LeftMenuComponent.ChooseLeftSectionOption<IngredientsPage>();
ingredientsPage.FiltersComponent.UseStringFilter(FiltersOptions.IngredientName, ingredientName);
ingredientsPage.ExportIngredientsElement.Click();
var downloadResult = DownloadHelper.WaitUntilDownloadedCompare(ingredientsExportFile);
string ingredientExportExcelFile = DownloadHelper.SeleniumDownloadPath + ingredientsExportFile;
var exelToByteArray1 = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, #"..\..\..") + #"\TestData\" + "ImportFiles" + #"\IngredientsImport.xlsx");
var excelArray1 = ExcelsExtensions.FileToByteArray(exelToByteArray1);
var excelArray2 = ExcelsExtensions.FileToByteArray(ingredientExportExcelFile);
if (excelArray1.DocContent.Length == excelArray2.DocContent.Length)
{
Console.WriteLine("Excels are equal");
DownloadHelper.CheckFileDownloaded(ingredientsExportFile);
}
else
{
Console.WriteLine("Excels are not equal");
DownloadHelper.CheckFileDownloaded(ingredientsExportFile);
Assert.Fail("Seems that imported and exported excels were not the same! Check it!");
}
}
What's the current status:
Above code works correctly speaking about getting .Lenght and compare it between two excels. Problem appears with different comparison where firstly the exported excel is placed inside .ZIP file. I need to unpack it and then compare. Although excel sheets are the same .Lenght value is different and it fails.
var downloadResult = DownloadHelper.WaitUntilDownloadedCompare(productsExportFile);
string stockProductZIPFile = DownloadHelper.SeleniumDownloadPath + productsExportFile;
string stockProductUnzippedFilePath = DownloadHelper.SeleniumDownloadPath + productsExportFile;
var pathToUnzip = DownloadHelper.SeleniumDownloadPath + productsExportFolderFile;
ZipFile zip = ZipFile.Read(stockProductZIPFile);
zip.ExtractAll(pathToUnzip);
string stockProductExportedExcel = DownloadHelper.SeleniumDownloadPath + "\\ProductsExport" + #"\Stock Products.xlsx";
var exelToByteArray1 = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, #"..\..\..") + #"\TestData\" + "ImportFiles" + #"\StockProduct.xlsx");
var excelArray1 = ExcelsExtensions.FileToByteArray(exelToByteArray1);
var excelArray2 = ExcelsExtensions.FileToByteArray(stockProductExportedExcel);
if (excelArray1.DocContent.Length == excelArray2.DocContent.Length)
{
Console.WriteLine("Excels are equal");
DownloadHelper.CheckFileDownloaded(stockProductUnzippedFilePath);
DownloadHelper.CheckFileDownloaded(pathToUnzip);
}
else
{
Console.WriteLine("Excels are not equal");
DownloadHelper.CheckFileDownloaded(stockProductUnzippedFilePath);
DownloadHelper.CheckFileDownloaded(pathToUnzip);
Assert.Fail("Seems that imported and exported excels were not the same! Check it!");
}
Ideas to solve
First of all I'm not sure if comparing those two by .Lenght is good idea. For one case it works but for the other it's not. I'm not sure if it is connected with packing sheet to .zip format and then unpacking it? Actually in second (broken) scenario products size actually differs. Oracle product has 4 KB and exported one has 10 KB (even thought their data inside is the same).

.Net Core: Reading data from CSV & Excel files

Using .net core & c# here.
I have a UI from which user can upload the Excel or CSV files. Once they upload this goes to my web api which handles the reading of the data from these files and returns json.
My Api code as:
[HttpPost("upload")]
public async Task<IActionResult> FileUpload(IFormFile file)
{
JArray data = new JArray();
using (ExcelPackage package = new ExcelPackage(file.OpenReadStream()))
{
ExcelWorksheet worksheet = package.Workbook.Worksheets[1];
//Process, read from excel here and populate jarray
}
return Ok(data );
}
In my above code I am using EPPlus for reading the excel file. For excel file it works all fine but it cannot read csv file which is the limitation of EPPlus.
I searched and found another library CSVHelper: https://joshclose.github.io/CsvHelper/ The issue with this is it does vice versa and can read from CSV but not from Excel.
Is there any library available which supports reading from both.
Or would it be possible use EPPlus only but convert uploaded CSV to excel on the fly and then read. (please note I am not storing the excel file anywhere so cant use save as to save it as excel)
Any inputs please?
--Updated - Added code for reading data from excel---
int rowCount = worksheet.Dimension.End.Row;
int colCount = worksheet.Dimension.End.Column;
for (int row = 1; row <= rowCount; row++)
{
for (int col = 1; col <= colCount; col++)
{
var rowValue = worksheet.Cells[row, col].Value;
}
}
//With the code suggested in the answer rowcount is always 1
You can use EPPLus and a MemoryStream for opening csv files into an ExcelPackage without writing to a file. Below is an example. You may have to change some of the the parameters based on your CSV file specs.
[HttpPost("upload")]
public async Task<IActionResult> FileUpload(IFormFile file)
{
var result = string.Empty;
string worksheetsName = "data";
bool firstRowIsHeader = false;
var format = new ExcelTextFormat();
format.Delimiter = ',';
format.TextQualifier = '"';
using (var reader = new System.IO.StreamReader(file.OpenReadStream()))
using (ExcelPackage package = new ExcelPackage())
{
result = reader.ReadToEnd();
ExcelWorksheet worksheet =
package.Workbook.Worksheets.Add(worksheetsName);
worksheet.Cells["A1"].LoadFromText(result, format, OfficeOpenXml.Table.TableStyles.Medium27, firstRowIsHeader);
}
}
Here's using Aspose, which is unfortunately not free, but wow it works great. My API is using the streaming capability with Content-Type: multipart/form-data rather than the IFormFile implementation:
[HttpPut]
[DisableFormValueModelBinding]
public async Task<IActionResult> UploadSpreadsheet()
{
if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
{
return BadRequest($"Expected a multipart request, but got {Request.ContentType}");
}
var boundary = MultipartRequestHelper.GetBoundary(MediaTypeHeaderValue.Parse(Request.ContentType), _defaultFormOptions.MultipartBoundaryLengthLimit);
var reader = new MultipartReader(boundary, HttpContext.Request.Body);
var section = (await reader.ReadNextSectionAsync()).AsFileSection();
//If you're doing CSV, you add this line:
LoadOptions loadOptions = new LoadOptions(LoadFormat.CSV);
var workbook = new Workbook(section.FileStream, loadOptions);
Cells cells = workbook.Worksheets[0].Cells;
var rows = cells.Rows.Cast<Row>().Where(x => !x.IsBlank);
//Do whatever else you want here
Please try with below code
private string uploadCSV(FileUpload fl)
{
string fileName = "";
serverLocation = Request.PhysicalApplicationPath + "ExcelFiles\\";
fileName = fl.PostedFile.FileName;
int FileSize = fl.PostedFile.ContentLength;
string contentType = fl.PostedFile.ContentType;
fl.PostedFile.SaveAs(serverLocation + fileName);
string rpath = string.Empty, dir = string.Empty;
HttpContext context = HttpContext.Current;
string baseUrl = context.Request.Url.Scheme + "://" + context.Request.Url.Authority + context.Request.ApplicationPath.TrimEnd('/') + '/';
try
{
rpath = serverLocation + fileName;//Server.MapPath(dir + fileName);
using (Stream InputStream = fl.PostedFile.InputStream)
{
Object o = new object();
lock (o)
{
byte[] buffer = new byte[InputStream.Length];
InputStream.Read(buffer, 0, (int)InputStream.Length);
lock (o)
{
File.WriteAllBytes(rpath, buffer);
buffer = null;
}
InputStream.Close();
}
}
}
catch (Exception ex)
{
lblSOTargetVal.Text = ex.Message.ToString();
}
return rpath;
}
Use the Open XML SDK package and add insert working solution for it.

How To Open File According To There File Extension Format Without Downloading File?

Here i am trying to open the file of any extension format in ASP.NET MVC CORE 2.0 that has been saved in data base according to the extension format of that file without downloading that file. For example lets say i have ms word file so when i click that file it should open in word, if i have pdf it should open in pdf format without downloading the file.
Now, the problem in my code is that it force to download the file instead of opening the file according to respective file extemsion format.
Any help will be a great and will be thank full.Thank You
Below is my code
public IActionResult ViewFileByFileId (int id)
{
DoctorCredentialDocsModel DoctorCredential = new DoctorCredentialDocsModel();
DoctorCredential = _doctorService.GetDoctorCredentialDetails(id);
string AttachPath = ConfigPath.DoctorCredentialsAttachmentPath;
string strFileFullPath = Path.Combine(AttachPath, DoctorCredential.AttachedFile);
string contentType = MimeTypes.GetMimeType(strFileFullPath);
if (!strFileFullPath.Contains("..\\"))
{
byte[] filedata = System.IO.File.ReadAllBytes(strFileFullPath);
var cd = new System.Net.Mime.ContentDisposition
{
FileName = DoctorCredential.FileName,
Inline = false,
};
Request.HttpContext.Response.Headers.Add("Content-Disposition", cd.ToString());
return File(filedata, contentType);
}
else
{
return new NotFoundResult();
}
}
Try yo send like tihs. FileContentResult may can help you :)
Lastly look at this :)
What's the difference between the four File Results in ASP.NET MVC
public FileContentResult ViewFileByFileId (int id)
{
DoctorCredentialDocsModel DoctorCredential = new DoctorCredentialDocsModel();
DoctorCredential = _doctorService.GetDoctorCredentialDetails(id);
string AttachPath = ConfigPath.DoctorCredentialsAttachmentPath;
string strFileFullPath = Path.Combine(AttachPath, DoctorCredential.AttachedFile);
string contentType = MimeTypes.GetMimeType(strFileFullPath);
if (!strFileFullPath.Contains("..\\"))
{
byte[] filedata = System.IO.File.ReadAllBytes(strFileFullPath);
var cd = new System.Net.Mime.ContentDisposition
{
FileName = DoctorCredential.FileName,
Inline = false,
};
Request.HttpContext.Response.Headers.Add("Content-Disposition", cd.ToString());
return File(filedata, contentType);
}
else
{
return new NotFoundResult();
}
}

Need to open and save Excel file before reading it

I have a method were I create an Excelsheet. When the file is created I need to open it and save it manually in Excel before I can read it with Excel Data Reader. If I open and save the exact same file without changeing anything I can read it like I wan't it to work. Does anyone know how I can:
a) Save it properly when creating the file (using EPPlus)?
or
b) Open the already created file and save it properly by using C# before I try to read it?
My create method:
public void CreateAnnuityExcelSheet(List<Calculation> cList, FormCollection form, int DTCyear)
{
string fileName = "test";
string path = #"C:\ExcelFiles\" + fileName + ".xlsx"; //Path for the file
FileInfo info = new FileInfo(path);
info.Directory.Create(); //If C:\ExcelFiles does not exist, create it
if (!info.Exists)
{
using (ExcelPackage package = new ExcelPackage(info))
{
ExcelWorksheet ws = package.Workbook.Worksheets.Add(fileName);
//Filling the worksheet with values here...
package.SaveAs(info);
}
}
}
My read method:
[HttpPost]
public ActionResult ShowExcelFile(GetExcel model)
{
List<Calculation> cList = new List<Calculation>();
DataSet result = null;
var file = model.Files[0];
if (file != null && file.ContentLength > 0)
{
// .xlsx
IExcelDataReader reader = ExcelReaderFactory.CreateOpenXmlReader(file.InputStream);
reader.IsFirstRowAsColumnNames = true;
result = reader.AsDataSet();
reader.Close();
var PV = Convert.ToDecimal(data.Table.Rows[1][6]); //Works fine if the file is opened and saved in Excel. Else null..
//Work with the dataset here. When the file is not opened and saved it gets null everywhere. Else it works fine
}
return View("ShowExcelFile", model);
}
I have also tried using WriteAllBytes instead of using package.SaveAs():
byte[] data = package.GetAsByteArray();
System.IO.File.WriteAllBytes(path, data);
This gets my the exact same result. I still need to open and save the file manually.

C# Saving an MP4 Resource to a file

I've tried a few different ways but it won't open when it's saved. How can I accomplish this?
Basically I want to be able to save an MP4 file that's currently a resource file to a temp location that I can access as a path.
Here's something I've tried:
public static void WriteResourceToFile(string resourceName, string fileName)
{
using (Stream s = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
{
if (s != null)
{
byte[] buffer = new byte[s.Length];
char[] sb = new char[s.Length];
s.Read(buffer, 0, (int)(s.Length));
/* convert the byte into ASCII text */
for (int i = 0; i <= buffer.Length - 1; i++)
{
sb[i] = (char)buffer[i];
}
using (StreamWriter sw = new StreamWriter(fileName))
{
sw.Write(sb);
sw.Flush();
}
}
}}
You're overcomplicating it.
Try something like this (note, not compiled or tested, and Stream.CopyTo() only exists in .NET 4.0 and later).
using (Stream s = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)))
using (FileStream fs = File.Open("c:\myfile.mp4", FileMode.Create))
{
s.CopyTo(fs);
}
Job done.
If you don't have .NET 4.0 available, you'll need to implement one yourself, like one of these: How do I copy the contents of one stream to another?
To get a list of all of the resource names in the current assembly, do something like this:
Assembly a = Assembly.GetExecutingAssembly();
foreach (string s in a.GetManifestResourceNames())
{
Console.WriteLine(s);
}
Console.ReadKey();
Take what turns up on the console and pass it into GetManifestResourceStream() in the first snippet I posted.
http://msdn.microsoft.com/en-us/library/system.reflection.assembly.getmanifestresourcenames.aspx
Why are you writing an MP4 as a string? You should write out bytes without modification. Your conversion to chars is modifying the data. Use The FileStream call and call the Write method.
you could try something like this:
I pasted the wrong code in.... sorry, i was in a hurry
[HttpPost]
public ActionResult Create(VideoSermons video, HttpPostedFileBase videoFile)
{
var videoDb = new VideoSermonDb();
try
{
video.Path = Path.GetFileName(videoFile.FileName);
video.UserId = HttpContext.User.Identity.Name;
videoDb.Create(video);
if (videoFile != null && videoFile.ContentLength > 0)
{
var videoName = Path.GetFileName(videoFile.FileName);
var videoPath = Path.Combine(Server.MapPath("~/Videos/"),
System.IO.Path.GetFileName(videoFile.FileName));
videoFile.SaveAs(videoPath);
}
return RedirectToAction("Index");
}
catch
{
return View();
}
}
this actually loads video files to a directory, but it should work for your format as well.
-Thanks,

Categories