Programatically Create Excel Sheets from different templates using a Addin - c#

I am developing an Excel Addin that is able to fetch data from our database.Instead of dumping the data directly , I would like to have the data presented in a nice format. I have got our local VBA expert to develop a templates for the same since there can be multiple sheets all of which can have different formats.
It is while adding the worksheet that I am stuck at.
string TemplateFileLocation = Path.GetFullPath(fileName);
if(File.Exists(fileName))
{
Worksheet newWorkSheet = (WorkSheet)Globals.ThisAddin.Aplication.Worksheets.Add(Missing.Value,Missing.Value,1,TemplateFileLocation);
}
The code crashes while it hits this location.
The Error code returned is : 0x800A03EC
I have verified that the path to the template file is correct.
Each of these templates have only one work sheet.

You can use EPPlus
using System.IO;
using System.Reflection;
using OfficeOpenXml;
//Create a stream of .xlsx file contained within my project using reflection
Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("EPPlusTest.templates.VendorTemplate.xlsx");
//EPPlusTest = Namespace/Project
//templates = folder
//VendorTemplate.xlsx = file
//ExcelPackage has a constructor that only requires a stream.
ExcelPackage pck = new OfficeOpenXml.ExcelPackage(stream);

Related

.NET & EEPlus: How do I read an Excel .xlsm file and then make changes to it?

I have a project where my goal is to produce an .xlsm Excel spreadsheet using .NET and the EEPlus 5.8.14 Excel Spreadsheet library. I can do this using EEPlus's documented techniques, (though some of these I cannot get to work). As I was working on this, I realized that what my code needed to do was relatively small, and it made sense to use an existing .xlsm file as a template and just make changes to what I needed to change using EEPlus.
So now I am including the .xlsm file as a resource compiled into the assembly. This works great, and I can read the file from the resources and produce it from my controller. But once read, this data inside EPPlus seems to be read-only. So while this produces an Excel file:
public ActionResult ExcelFile(){
const string ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Byte[] bytes = Properties.Resources.AssetsEntry;
string fstem = Path.GetRandomFileName();
int unique = 0;
string filePath = String.Format("{0}#AutoGen_{1}_{2}.{3}", Path.GetTempPath(), fstem, ++unique, "xlsm");
var outStream = System.IO.File.OpenWrite(filePath);
var writer = new BinaryWriter(outStream);
writer.Write(bytes);
outStream.Close();
ExcelPackage excelPackage = new ExcelPackage(filePath);
var sheet = excelPackage.Workbook.Worksheets[1];
//place where I might want to change data
//sheet.Cells["B3"].Value = "testing";
var excelData = excelPackage.GetAsByteArray();
var fileName = "ExcelFile.xlsm";
return File(excelData, ContentType, fileName);
}
If I try to uncomment out the second commented-out line, that code fails to change the resulting Excel spreadsheet (though there is no error). How do I go about reading in an Excel spreadsheet and making changes using EEPlus?
UPDATE: I can add new worksheets to an uploaded spreadsheet, and I can alter those added sheets. But I cannot alter data on uploaded worksheets. Fortunately, for this particular project, that is acceptable. But it would be frustrating if I wanted to be able to set up a worksheet in Excel and then populate it programmatically.

NPOI corrupting xlsm workbook

I am required to write some data into an macro enabled workbook which was developed in 1998, i am using NPOI dotnet core library for this task. I am able to write the values into the excel correctly, however i am seeing that alignment and formatting of the sheets is lost. Screenshots below:
First one shows the file after open the file using NPOI and downloading the same, and second shows the file when it is locally opened.
below is the code i am using
public XSSFWorkbook OpenExcelFile(string filePath, string tempSavePath)
{
using (var stream = new FileStream(tempSavePath, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
var temphssfwb = new XSSFWorkbook(OPCPackage.Open(filePath));
temphssfwb.Write(stream);
}
XSSFWorkbook hssfwb;
hssfwb = new XSSFWorkbook(OPCPackage.Open(tempSavePath));
hssfwb.CreateSheet("casevalidationsheet");
return hssfwb;
}
Can someone please help me understand why NPOI is ruining the alignment of my excel workbook?

EPPlus with OpenXML and streams

I am trying to automate a Powerpoint presentation. I am using OpenXML to navigate the powerpoint presentation up to the point that I find the Excel linked to a chart. Now I want to use EPPlus to load a datatable into one of the worksheets (because EPPlus has a simple LoadFromDataTable function whereas I think I would have to write lots of code to use OpenXML).
So my problem is this.
I have a PresentationDocument in memory. And I have navigated to the particular chart that I want to manipulate via:
doc.PresentationPart.SlideParts.ElementAt(0).ChartParts.ElementAt(0)
I get the Excel part using:
var stream = chartpart.EmbeddedPackagePart.GetStream()
Then I tried:
using(var pck = new ExcelPackage(stream)) {
`do stuff;
`pck.Save();
}
and then at the end I do a doc.PresentationPart.Presentation.Save but this hasn't changed the Presentation. I can change it using OpenXML instead with:
using (var xl = Spreadsheet.Document.Open(stream, true))
{
`do stuff;
`xl.Close();
}
With everything else the same. So I guess either xl.Close() is doing stuff that pck.Save() isn't or I am using the stream incorrectly - can anyone advise?

C# Read Excel using late binding

Hi
I have not used late binding before but it would seem to be the solution, if only I could find a concise example!
Or may be it's not the solution but I'm sure you guys will know!
I need to fill a dropdown combbox list from a column in excel reading down to the first blank cell. the solution needs to work with excel 2003 and above some PCs never have had 2003 install only office 2010 other have been upgraded from 2003 and some are still on 2003!
I need a solution that works on all of the above.
So I'm looking into late binding is this the correct way to go? would Linq help!?
Its a clasic windows Form app using .Net 4.
I thought I would write a method that takes the file name and path and returns a list which I would then assign to the combobox.
But being new I'm not getting pass go!
Any help/examples PLEASE
It sounds like you're looking at using COM interop/automation with the Excel application installed on client machines.
If your sole requirement is to extract data from an Excel file, you'll be better off using a library that can simply read data out of the file itself, rather than launching the Excel process in the background.
It is faster, cleaner, and more testable.
I've used NPOI for .xls files (and there are certainly others), and there are LOTS of options for .xlsx files. This SO question is about creating a file, but any of the suggested libraries can of course read files as well.
The only time I'd use COM automation is to interact with a running instance of Excel.
Edit (in response to comments)
Here is a sample of getting the values of column B as strings:
using System;
using System.IO;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var stream = new FileStream(#"c:\my_workbook.xls", FileMode.Open);
var workbook = new HSSFWorkbook(stream);
stream.Close();
var sheet = workbook.GetSheet("My Sheet Name");
var row_enumerator = sheet.GetRowEnumerator();
while (row_enumerator.MoveNext())
{
var row = (Row)row_enumerator.Current;
var cell = row.GetCell(1); // in Excel, indexes are 1-based; in NPOI the indexes are 0-based
Console.WriteLine(cell.StringCellValue);
}
Console.ReadKey();
}
}
}

Read excel file from a stream

I need a way to read a Excel file from a stream. It doesn't seem to work with the ADO.NET way of doing things.
The scenario is that a user uploads a file through a FileUpload and i need to read some values from the file and import to a database.
For several reasons I can't save the file to disk, and there is no reason to do so either.
So, anyone know of a way to read a Excel file from a FileUpload stream?
It seems i found a soultion to the problem myself.
http://www.codeplex.com/ExcelDataReader
This library seems to work nicely and it takes a stream to read the excel file.
ExcelDataReader reader = new ExcelDataReader(ExcelFileUpload.PostedFile.InputStream);
This can be done easily with EPPlus.
//the excel sheet as byte array (as example from a FileUpload Control)
byte[] bin = FileUpload1.FileBytes;
//gen the byte array into the memorystream
using (MemoryStream ms = new MemoryStream(bin))
using (ExcelPackage package = new ExcelPackage(ms))
{
//get the first sheet from the excel file
ExcelWorksheet sheet = package.Workbook.Worksheets[1];
//loop all rows in the sheet
for (int i = sheet.Dimension.Start.Row; i <= sheet.Dimension.End.Row; i++)
{
//loop all columns in a row
for (int j = sheet.Dimension.Start.Column; j <= sheet.Dimension.End.Column; j++)
{
//do something with the current cell value
string currentCellValue = sheet.Cells[i, j].Value.ToString();
}
}
}
SpreadsheetGear can do it:
SpreadsheetGear.IWorkbook workbook = SpreadsheetGear.Factory.GetWorkbookSet().Workbooks.OpenFromStream(stream);
You can try it for yourself with the free evaluation.
Disclaimer: I own SpreadsheetGear LLC
Infragistics has an excel component that can read an excel file from a stream.
I'm using it in a project here and it works well.
Also the open source myXls component could easily be modified to support this. The XlsDocument contstructor only supports loading from a file given by a file name, but it works by creating a FileStream and then reading the Stream, so changing it to support loading from streams should be trivial.
Edit:
I see that you found a solution but I just wanted to note that I updated the source code for the component so that it now can read an excel file directly from a stream. :-)
I use ClosedXML nuget package to read excel content from stream. It has a constructor overload in XLWorkbook class which takes stream pointing to an excel file (aka workbook).
imported namespace at the top of your code file:
using ClosedXML.Excel;
Source code:
var stream = /*obtain the stream from your source*/;
if (stream.Length != 0)
{
//handle the stream here
using (XLWorkbook excelWorkbook = new XLWorkbook(stream))
{
var name = excelWorkbook.Worksheet(1).Name;
//do more things whatever you like as you now have a handle to the entire workbook.
var firstRow = excelWorkbook.Worksheet(1).Row(1);
}
}

Categories

Resources