Copy Excel template in another template with pictures - c#

I try to merge two Excel templates together in C#. Everything works fine except for the pictures in the second template that aren't merged.
I use the following steps to achieve my objective :
Load the first template
Add content to the first template
Load the second template
Copy the template's content in the clipboard
Paste the clipboard's content in the current Worksheet
Sadly, I have no control over the templates themselves as they are provided by the client and I can't change them.
Here's the code :
public static void MergeTemplates()
{
ExcelApp app = new ExcelApp();
var path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
app.Workbooks.Open($"{path}\\Excel1.xltx", true);
var workbook = app.Workbooks[1];
var sheet = workbook.Worksheets[1];
sheet.Range["A1"].Value = "Sometext";
//Loading the second template, which has images.
var xlTemp = app.Workbooks.Open($"{path}\\Excel2.xltx", true);
var xlSheetTemp = xlTemp.Worksheets[1];
xlSheetTemp.Range["A1", "C10"].Copy();
//Add the second template at the end of the first
sheet.Range["A2","C11"].PasteSpecial();
xlTemp.Close();
workbook.SaveAs($"{path}\\Test.xlsx");
workbook.Close();
app.Quit();
}
At the end, the images of Excel2.xltx aren't imported in the saved Test.xlsx document.
How can I merge the two templates so that the images will be included?

Related

How to set active sheet with Open XML SDK 2.5

using the example here How to Copy a Worksheet within a Workbook
I have successfully been able to clone/copy sheets in my excel file, however when I open the excel the 2nd sheet is the active(visible) sheet. I haven't been able to locate a property that could do thins.....Is there any way to specify what sheet is active?
I've tried to force it by opening and editing the first sheet in the file thinking it was the last edited sheet that was active but that didn't work either.
any help would be great. TIA
update: looking at the workbook.xml created when renaming the .xlsx to .zip I came accross the 'activeTab' property. made a quick change to my code and seems to work just fine
public void SetFirstSheetInFocus(String xlsxFile)
{
using (SpreadsheetDocument spreadSheet = SpreadsheetDocument.Open(xlsxFile, true))
{
//Get a reference to access the main Workbook part, which contains all references
WorkbookPart _workbookPart = spreadSheet.WorkbookPart;
if (_workbookPart != null)
{
WorkbookView _workbookView = spreadSheet.WorkbookPart.Workbook.BookViews.ChildElements.First<WorkbookView>();
if (_workbookView != null)
{
_workbookView.ActiveTab = 0; // 0 for first or whatever tab you want to use
}
// Save the workbook.
_workbookPart.Workbook.Save();
}
}
}
If the name of your sheet is in the variable
sheetName
you can set the sheet with that name active like this:
using (var spreadsheetDoc = SpreadsheetDocument.Open(emptyHIPTemplatePath, true /* isEditable */, new OpenSettings { AutoSave = false }))
{
var workbookPart = spreadsheetDoc.WorkbookPart;
var workBook = spreadsheetDoc.WorkbookPart.Workbook;
var sheet = workBook.Descendants<Sheet>().FirstOrDefault(s => s.Name == sheetName);
var sheetIndex = workBook.Descendants<Sheet>().ToList().IndexOf(sheet);
var workBookView = workBook.Descendants<WorkbookView>().First();
workBookView.ActiveTab = Convert.ToUInt32(sheetIndex);
...
workBook.Save();
}
From Vincent Tan's book:
The SheetId property doesn't determine the order. The order of
appending the Sheet classes to the Sheets class, does.
When you add a sheet, it gets the next index, but a single sheet does not have an index. OpenXML gives it an index when you are done adding sheets. Again, from Vincent Tan's book:
Let's say you have 3 worksheets named Sheet1, Sheet2 and Sheet3.
However, when you appended the corresponding Sheet classes, you did it
as Sheet2, Sheet3 and Sheet1, in that order.

mso-data-placement:same-cell not working

I am exporting data into Excel from a web page. This should be a no brainer, but there are <p> tags in the data. This causes Excel to create new rows when the data should all be in the same cell. After some research I found that mso-data-placement should do the trick, but it's not working. Excel opens, the data is displayed, but extra uncessary rows are created. Here is the code I use to export the data:
protected void doexcel()
{
string style = #"<style type='text/css'>P {mso-data-placement:same-cell; font-weight:bold;}</style>";
HttpResponse response = HttpContext.Current.Response;
// first let's clean up the response.object
response.Clear();
response.Charset = "";
//set the response mime type for excel
response.ContentType = "application/vnd.ms-excel";
Random RandomClass = new Random();
int RandomNumber = RandomClass.Next();
String filename = "a" + RandomNumber + DateTime.Now + ".xls";
response.AddHeader("Content-Disposition", "attachment;filename=\"" + filename + "\"" );
// create a string writer
using (StringWriter sw = new StringWriter())
{
using (HtmlTextWriter htw = new HtmlTextWriter(sw))
{
HttpContext.Current.Response.Write(style);
SqlDataSourceEmployeeAssets.ConnectionString = MyObjects.Application.CurrentContext.ConnectionString;
String sql = (string)Session["sql"];
SqlDataSourceEmployeeAssets.SelectCommand = sql;
// lCount.Text = "Query returned " + getCount(query) + " rows.";
DataGrid dge = new DataGrid();
dge.DataSource = SqlDataSourceEmployeeAssets;
dge.DataBind();
dge.RenderControl(htw);
response.Write(sw.ToString());
response.End();
}
}
}
This is an example of the raw data in the database that is giving me grief:
<P>4/13/2011 : Cheng "Jonathan" Vaing is with BSES Graffiti Unit.</P><P>4/13/2011 : Cheng "Jonathan" Vaing is with</P>
Suggestions?
I tried a couple of other things
I went straight to the data and added the mso-data-placement attribute to the paragraph tag inline. Still didn't work. The data looked like this
<P style="mso-data-placement:same-cell> my data </p>
I tried other mso-* attributes, that didn't work either. For example, I changed my stylesheet to look like this
<style type='text/css'>P {mso-highlight:yellow}</style>";
Why oh why doesn't Excel recognize my mso-* attributes?!?!
There is a solution but it is not clean.
After the dge.DataBind, place the following code. This will encode the text of each cell
foreach (DataGridItem dgi in dge.Items)
{
foreach (TableCell cell in dgi.Cells)
{
cell.Text = WebUtility.HtmlEncode(cell.Text);;
}
}
The Excel file, when opened, should show the raw data with the markup, all in one cell.
I found that this works because Excel actually encodes the text, as well. To see what Excel does in action, do the following:
Create a new workbook in Excel (I am using Office 2013).
In the first cell, paste the raw data (as you have it displayed). Do this by first pressing F2 (insert into cell), then paste the text.
Save the workbook as an HTML file (or web page).
Using windows explorer, go to the folder location of where you saved the file. There should be a hidden folder (i think it is hidden) with the same name as your file. For example, if your workbook is Book1.htm, there should be a folder labeled Book1_files.
In this folder, there should be an HTM file with the name sheet001.htm. Open this file in notepad (or any text editor...not excel or word)
Locate your raw data. You will see that the text is not showing the HTML markup, rather it is showing the encoded version.
Hope this helps.

Export xps to pdf in C#

I am a newbie and i want to generate PDF from Infragistics, Xamdatagrid. However as Infragistics doesnt provide this functionality ,i have generated XPS of Xamdatagrid and wants to convert that to XPS programitically. What are the possible work around and third party tool to do that?
If you export the xamDataGrid in an excel file then is pretty simple to use Excel.Interop and ask excel to export its workbook in PDF format
// Export an excel workbok in PDF format with landscape orientation
private static void ExportWorkbookToPDF(string workbook, string output)
{
Microsoft.Office.Interop.Excel.Application excelApplication =
new Microsoft.Office.Interop.Excel.Application();
excelApplication.ScreenUpdating = false;
excelApplication.DisplayAlerts = false;
excelApplication.Visible = false;
Microsoft.Office.Interop.Excel.Workbook excelWorkbook =
excelApplication.Workbooks.Open(workbook);
if (excelWorkbook == null)
{
excelApplication.Quit();
excelApplication = null;
excelWorkbook = null;
throw new NullReferenceException("Cannot create new excel workbook.");
}
try
{
((Microsoft.Office.Interop.Excel._Worksheet)excelWorkbook.ActiveSheet).PageSetup.Orientation =
Microsoft.Office.Interop.Excel.XlPageOrientation.xlLandscape;
excelWorkbook.ExportAsFixedFormat(XlFixedFormatType.xlTypePDF, output);
}
finally
{
excelWorkbook.Close();
excelApplication.Quit();
excelApplication = null;
excelWorkbook = null;
}
}
if you wish to create only pdf. then the simplest thing have any pdf printer on machine. One like PDF Creater and then just call the printing thing like below on the XamDataGrid.
make sure you select the PDF Printer on the Printer Selection Dialog Box.
// 1. Create Report object
Report reportObj = new Report();
// 2. Create EmbeddedVisualReportSection section.
// Put the grid you want to print as a parameter of section's constructor
EmbeddedVisualReportSection section = new EmbeddedVisualReportSection(xamdg);
// 3. Add created section to report's section collection
reportObj.Sections.Add(section);
// Optional. If you have progress indicator set its Report property to created report
// progressInfo.Report = reportObj;
// 4. Call print method
reportObj.Print(true, false);
You can also use thirdparty software like GhostXPS.
http://www.ghostscript.com/download/gxpsdnld.html
Just start the convert process with the correct arguments and it will generate the PDF for you. The drawback is that you have to save the files temporary to the disk and check the return code. Also make sure you are not violating the GNU license

Export data from DataTable to Excel file

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.

Creating excel document as attachment on a sharepoint list

I've got some problems adding a excel document as attachment on a custom list. I've made an eventreceiver which collects data from other lists and puts the data into an excel document.
What i've tried to do to correct the problem:
tested CreateContentRow(index, item) in a separate console application (works)
checked if theres something wrong with fetching information from other lists (works)
tried saving to a document library (the file gets saved without content)
tried to open the xlsx document to se if there's something wrong with the xml (no custom xml added).
The code works just fine, but the document is saved but it's identical to the template, no content added.
using (var memory = new MemoryStream())
{
var binary = template.OpenBinary();
memory.Write(binary, 0, binary.Length);
using (var document = SpreadsheetDocument.Open(memory, true))
{
var workbookPart = document.WorkbookPart;
var worksheetparts = workbookPart.WorksheetParts;
var worksheetpart = worksheetparts.FirstOrDefault();
var sheetData = worksheetpart.Worksheet.GetFirstChild<SheetData>();
var index = 2;
foreach (var item in items)
{
var row = CreateContentRow(index, item);
index++;
sheetData.AppendChild(row);
}
properties.ListItem.Attachments.Add("name" + string.Format("{0:yyyy-MM-dd_HHmmss}", DateTime.Now) + ".xlsx", memory.ToArray());
properties.ListItem.Update();
}
}
I'm using the same approach on another list where i generate .docx documents there it works just fine. Is there a big difference in how i should save the document depending on if its .xlsx or .docx ?
When i debug the cells and rows are added to the sheetdata, but it does not get saved. Any ideas on how to fix this ?
In order to get the content saved i needed to add save statements.
wspart.Worksheet.Save();
document.WorkbookPart.Workbook.Save();
When i added the lines above before adding the attachemnt everything worked as it should.

Categories