So i think ive tried everything now. Im trying to get the values from radiobuttons and checkboxes from an excel sheet. My first approach was to use the Excel Data Reader: http://exceldatareader.codeplex.com/. The cells with checkboxes render empty.
Same thing if i use OLEDB;
string filename = #"C:\\" + "uploads\\SmartAuditSheet.xls";
string connectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" +
"Data Source=" + filename + ";" +
"Extended Properties=Excel 8.0;";
OleDbDataAdapter dataAdapter = new OleDbDataAdapter("SELECT * FROM [Sheet1$]", connectionString);
DataSet myDataSet = new DataSet();
dataAdapter.Fill(myDataSet, "BookInfo");
DataTable dataTable = myDataSet.Tables["BookInfo"];
gv.DataSource = myDataSet;
gv.DataBind();
Help please.
I would suggest you try something like the following.
OLEObject ole = (OLEObject)excelWorksheet.OLEObjects("Checkbox1");
I would recommend using some 3rd-party library for that - there are several out there (free and commercial) that do NOT require Excel being installed:
OpenXML 2.0 (free library from MS) can be used to read/modify the content of an .xlsx so you can do with it what you want
EPPlus (free library) works with XLSX
some (commercial) 3rd-party libraries come with grid controls allowing you to do much more with excel files (most can do not only XLSX but XLS too) in your application (be it Winforms/WPF/ASP.NET...) like SpreadsheetGear, Aspose.Cells, Flexcel etc.
bool state = Convert.ToBoolean(ws.OLEObjects("Checkbox1").Object.value());
You get the object values using OpenXML. Below Code shows how to get checkbox object values using OpenXML.
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
public static bool GetCheckBoxValue( String filePath )
{
bool isChecked = false;
using (SpreadsheetDocument document = SpreadsheetDocument.Open(filePath, false))
{
WorkbookPart wbPart = document.WorkbookPart;
// Sheet object to retrieve a reference to the first worksheet.
Sheet theSheet = wbPart.Workbook.Descendants<Sheet>().Where(s => s.Name == "Sheet1").FirstOrDefault();
var control = wsPart.Worksheet.Descendants<DocumentFormat.OpenXml.Spreadsheet.Control>().FirstOrDefault();
var controlProperies = (ControlPropertiesPart)wsPart.GetPartById(control.Id);
isChecked = controlProperies.FormControlProperties.Checked == "Checked";
}
return isChecked ;
}
Related
I am trying to embed object into .xlsx document and copy sheets with embedded objects.
1. Copying sheets
This looks like straight forward issue. I have created method to copy the sheets:
static void CopySheetInsideWorkbook(string filename, string sheetName, string clonedSheetName)
{
using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(filename, true))
{
WorkbookPart workbookPart = spreadsheetDocument.WorkbookPart;
WorksheetPart sourceSheetPart = GetWorksheetPartByName(spreadsheetDocument, sheetName);
SpreadsheetDocument tempSheet =
SpreadsheetDocument.Create(new MemoryStream(), spreadsheetDocument.DocumentType);
WorkbookPart tempWorkbookPart = tempSheet.AddWorkbookPart();
WorksheetPart tempWorksheetPart = tempWorkbookPart.AddPart<WorksheetPart>(sourceSheetPart);
WorksheetPart clonedSheet = workbookPart.AddPart<WorksheetPart>(tempWorksheetPart);
Sheets sheets = workbookPart.Workbook.GetFirstChild<Sheets>();
Sheet copiedSheet = new Sheet
{
Name = clonedSheetName,
Id = workbookPart.GetIdOfPart(clonedSheet),
SheetId = (uint) sheets.ChildElements.Count + 1
};
sheets.Append(copiedSheet);
workbookPart.Workbook.Save();
}
}
The ouput is as expected but the embedded files are copied as "Picture" rather than "Object". I unzipped .xlsx file and all looks legit ie. similar to the sheet I copied. Yet still the file cannot be opened on the copied sheet. All images, strings are displayed in correct way.
2. Embedding the object
What I understand I need to do is:
Convert object into oleObject - this will be separate fun.
Add DrawingsPart - It looks like it's read-only and I can only add ImagePart.
Embed Object
Connect both drawing and embedded object part toghether and allocate to some range in spreadsheet.
static void EmbedFileXlsx(string path, string embeddedFilePath, string placeholderImagePath)
{
using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(path, true))
{
WorksheetPart sourceSheetPart = GetWorksheetPartByName(spreadsheetDocument, "Test");
var imagePart = sourceSheetPart.AddImagePart(ImagePartType.Emf, "rId1");
imagePart.FeedData(File.Open(placeholderImagePath, FileMode.Open));
var embeddedObject =
sourceSheetPart.AddEmbeddedObjectPart(#"application/vnd.openxmlformats-officedocument.oleObject");
embeddedObject.FeedData(File.Open(embeddedFilePath, FileMode.Open));
spreadsheetDocument.Save();
}
}
This code just adds embedded objects into the file but does not create any type of relationship between them. This means that file is not visible on the spreadsheet.
I tried copying sheets using ClosedXML as well but unfortunately this is not supported nor the embedding.
I also managed to understand how I can copy sheet into new document with all embedded objects using .xml files inside spreadsheet but I do not think this would be much productive and I would like to achieve this using all the methods inside OpenXML. It looks everything is there but something is amiss.
I am no expert in this, but could this help you on your way?
spreadsheetDocument.CreateRelationshipToPart(SOME ID);
I have had an issue for the last few hours trying to pull the sheet names from an excel workbook and display for selection in a combobox. I managed to get it to work but i'm a little concerned its crude and not very efficient.
private void btnChoose2_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog openfileDialog1 = new OpenFileDialog();
if (openfileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
openLabel.Text = openfileDialog1.SafeFileName;
String filename = DialogResult.ToString();
var excelApp = new Microsoft.Office.Interop.Excel.Application();
excelApp.Visible = false;
excelApp.Workbooks.Open(openfileDialog1.FileName);
int rcountTag = excelApp.Sheets.Count - 1;
for (int i = 1; i <= rcountTag + 1; i++)
{
Microsoft.Office.Interop.Excel.Sheets excelSheets = excelApp.Worksheets;
Microsoft.Office.Interop.Excel.Worksheet worksheet = (Microsoft.Office.Interop.Excel.Worksheet)
excelSheets.get_Item(i);
comboBoxMapping.Items.Insert(i - 1, worksheet.Name);
}
}
}
Any advice would be greatly appreciated.
You should look at using a 3rd party library for this that will make your life much easier than messing with interop.
Excel Data Reader
This will let you get all the sheet names and read data into a DataTable which then you can access however you want to get whatever data you need out of it. The GitHub Read Me page has simple examples that should solve your issue for you.
I would recommend EPPLUS if xlsx Excel format is to be dealt with.
Install epplus library from nuget package manager:
Then using OfficeOpenXml;
Get the list of sheet names:
ExcelPackage DocInv = new ExcelPackage(new FileInfo(ExcelDocument));
DocList = DocInv.Workbook.Worksheets.AsEnumerable().Select(x => x.Name).ToList();
The Problem
I'm trying to create a small program that uses an Excel template to create an Excel document and then writes to several cells using EPPlus. Unfortunately, the files appear to be corrupt no matter what I try.
My code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OfficeOpenXml;
using System.IO;
namespace ConsoleApplication9
{
public sealed class ExcelSerialize
{
private readonly List<Tuple<string, string>> Results;
private readonly string Directory;
private ExcelPackage package;
public ExcelSerialize(List<Tuple<string, string>> Results, string Directory)
{
this.Results = Results;
this.Directory = Directory;
}
public bool WriteResults()
{
FileInfo template = new FileInfo(Directory);
using (package = new ExcelPackage(template, true))
{
ExcelWorksheet worksheet = package.Workbook.Worksheets[1];
//foreach (Tuple<string, string> Result in Results)
//{
// worksheet.Cells[Result.Item1].Value = Result.Item2;
//}
string file = string.Format(System.AppDomain.CurrentDomain.BaseDirectory.ToString() + #"results\results" + System.DateTime.Now.ToString().Replace(" ", "").Replace("/", "_").Replace(":", "-") + ".xlsx");
Byte[] bin = package.GetAsByteArray();
File.WriteAllBytes(file, bin);
return true;
}
}
}
}
Things I've tried:
Changing the values of various cells in the template.
Saving an Excel document created from the template without writing any new data to it.
Creating a basic template with the cells A1, A2, and A3 containing "TEST" and no other edits instead of the more complicated template I intend to use.
Saving using Package.SaveAs().
Saving using the Byte array seen in the example code.
Compiling EPPlus from the latest source provided on Codeplex.
Things that work:
Creating a new file using the following code:
using (package = new ExcelPackage(string.Format(System.AppDomain.CurrentDomain.BaseDirectory.ToString() + #"results\results" + System.DateTime.Now.ToString().Replace(" ", "").Replace("/", "_").Replace(":", "-") + ".xlsx"))
{
ExcelWorksheet worksheet = package.Workbook.Worksheets.Add("Test");
worksheet.Cells[A1].Value = "Test";
package.Save();
}
Notes:
For whatever reason, the files saved still appear corrupt and can't be recovered. I'm currently using Microsoft Office 2010. The file formats I'm using are .xltx and .xlsx.
Short Answer:
The EPPlus library does not support creation of a file from an existing xltx Excel template.
Use a pre-formatted xlsx file instead.
Long Answer:
Dim excelFile As New FileInfo(filename)
Dim reportTemplate As New FileInfo(templatePath)
Dim xlFile As ExcelPackage = New ExcelPackage(excelFile, reportTemplate)
' Do Stuff
xlFile.Save()
When instantiating a new ExcelPackage object using EPPlus you're supposed to be able to provide a template as the second parameter (see code snippet above), however when providing it with an xltx file I kept getting a corrupt output file same as the user above. I eventually found that supplying a regular xlsx file as the template, rather than an actual template file, appeared to work.
This is an open source package, so I decided to take a quick look at the source.
It looks like the ExcelPackage constructors that accept the "template" parameter, call the CreateFromTemplate() method. The comments on the CreateFromTemplate() method states that it expects an existing xlsx file to use as a template, not an actual template file.
So while one might assume that the 'template' parameter refers to an actual xltx template file, it appears that EPPlus does not support that.
Similar problem faced, this worked by just giving me back the template
public ExcelPackage getSheet(string templatePath){
FileInfo template = new FileInfo(templatePath);
ExcelPackage p = new ExcelPackage(template, true);
ExcelWorksheet ws = p.Workbook.Worksheets[1]; //position of the worksheet
ws.Name = bookName;
p.Save();
ExcelPackage pck = new ExcelPackage(new System.IO.MemoryStream(), p.Stream);
return pck;
Then you call with this
string path = Server.MapPath(#"../../../Ex/template.xlsx")
try
{
OfficeOpenXml.ExcelPackage pck = getSheet(path);
Response.Clear();
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("content-disposition", String.Format(System.Globalization.CultureInfo.InvariantCulture, "attachment; filename={0}", fileName + ".xlsx"));
Response.BinaryWrite(pck.GetAsByteArray());
Response.End();
}
catch { }
Explicitly close the File after you write the data to it.
I know when you use EPPlus in a response on a web request closing the response removes that issue.
I have DataTable object. How can I export it into an XLS file?
I tried to render it via DataGrid
DataGrid dgGrid = new DataGrid();
dgGrid.DataSource = dt;
dgGrid.DataBind();
dgGrid.RenderControl(hw);
but the file is very large and the OutOfMemoryException appears.
I can use http://epplus.codeplex.com/.
I need C# function.
There are a number of options, one of them being the Access OLE DB Provider which also operates in terms of DataTables.
If you want more fine-grained support over the document, I'd recommend the Open XML SDK 2.0, whixh is .xmlx only.
For raw data, I think that Access OLE DB (also reffered to as the ACE provider) is the best choice since it enables a database-like experience. Open XML assumes fairly good knowledge of XML and the willingnes to experiment a bit more. On the other hand, you can apply formatting, add formulas and other advanced features.
Ok, find a solution here: http://bytesofcode.hubpages.com/hub/Export-DataSet-and-DataTable-to-Excel-2007-in-C
Just download epplus library and call method:
private void GenerateExcel(DataTable dataToExcel, string excelSheetName)
{
string fileName = "ByteOfCode";
string currentDirectorypath = Environment.CurrentDirectory;
string finalFileNameWithPath = string.Empty;
fileName = string.Format("{0}_{1}", fileName, DateTime.Now.ToString("dd-MM-yyyy"));
finalFileNameWithPath = string.Format("{0}\\{1}.xlsx", currentDirectorypath, fileName);
//Delete existing file with same file name.
if (File.Exists(finalFileNameWithPath))
File.Delete(finalFileNameWithPath);
var newFile = new FileInfo(finalFileNameWithPath);
//Step 1 : Create object of ExcelPackage class and pass file path to constructor.
using (var package = new ExcelPackage(newFile))
{
//Step 2 : Add a new worksheet to ExcelPackage object and give a suitable name
ExcelWorksheet worksheet = package.Workbook.Worksheets.Add(excelSheetName);
//Step 3 : Start loading datatable form A1 cell of worksheet.
worksheet.Cells["A1"].LoadFromDataTable(dataToExcel, true, TableStyles.None);
//Step 4 : (Optional) Set the file properties like title, author and subject
package.Workbook.Properties.Title = #"This code is part of tutorials available at http://bytesofcode.hubpages.com";
package.Workbook.Properties.Author = "Bytes Of Code";
package.Workbook.Properties.Subject = #"Register here for more http://hubpages.com/_bytes/user/new/";
//Step 5 : Save all changes to ExcelPackage object which will create Excel 2007 file.
package.Save();
MessageBox.Show(string.Format("File name '{0}' generated successfully.", fileName)
, "File generated successfully!", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
First of all, Google is your best friend. Also you can search on this site.
Some solutions:
You can write an excel file with SQL.
You can use the reference to Microsoft Office library to create an excel file
You can write an XML file.
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Create Excel (.XLS and .XLSX) file from C#
I have some code that generates a zip file that contains multiple CSV files and streams it back to the user (no file is saved on the server). However, I want to create an excel workbook instead (can be traditional xls or Office Open XML xlsx format) with each CSV 'file' being a spreadsheet.
How can I do this, without resorting to Office Automation on the server or a commercial 3rd party component?
You can use OleDB to generate simple tables in Excel files.
Note that you will need to generate a temp file on the server.
Example.
Note that their example is incorrect and needs to use an OleDbConnectionStringBuilder, like this:
OleDbConnectionStringBuilder builder = new OleDbConnectionStringBuilder();
if (isOpenXML)
builder.Provider = "Microsoft.ACE.OLEDB.12.0";
else
builder.Provider = "Microsoft.Jet.OLEDB.4.0";
builder.DataSource = fileName;
builder["Extended Properties"] = "Extended Properties=\"Excel 8.0;HDR=YES;\""
using (var con = new OleDbConnection(builder.ToString())) {
...
}
The XML format for Excel is quite simple and there's absolutely no need to do any automation.
The full reference is up on MSDN: http://msdn.microsoft.com/en-us/library/aa140066(office.10).aspx
Response.ContentType = "application/vnd.ms-excel";
The ContentType property specifies the HTTP content type for the response. If no ContentType is specified, the default is text/HTML.
Get all your data in a DataGrid and then get it from it can be done with:
DataGrid.RenderControl
Outputs server control content to a provided HtmlTextWriter object and stores tracing information about the control if tracing is enabled.
SqlConnection cn = new SqlConnection("yourconnectionstring");
cn.Open();
SqlDataAdapter da = new SqlDataAdapter("SELECT * FROM Users", cn);
DataTable dt = new DataTable();
da.Fill(dt);
DataGrid dg = new DataGrid();
dg.DataSource = dt;
dg.DataBind();
System.IO.StringWriter tw = new System.IO.StringWriter();
System.Web.UI.HtmlTextWriter hw = new System.Web.UI.HtmlTextWriter(tw);
dg.RenderControl(hw);
cn.Close();
Response.Clear();
Response.ContentType = "application/vnd.ms-excel";
this.EnableViewState = false;
Response.Write(tw.ToString());
Response.End();
You can write the excel xml by yourself. Here is a nice lib for the task, maybe it is something for you.
// Edit
Link: http://www.carlosag.net/Tools/ExcelXmlWriter/Generator.aspx