I am currently able to create a new Excel spreadsheet, write to it and save the spreadsheet through X++.
I have a few methods within a new class, each intended to write to a separate worksheet within the workbook.
The first method creates the spreadsheet, writes the data, saves the spreadsheet, and then quits Excel just fine. But within the next method I attempt to open the saved spreadsheet, write to another worksheet (tab), save again, and quit Excel.
The second method causes the following error.
Method 'saveAs' in COM object of class '_Workbook' returned error code 0x800A03EC () which means: You cannot save this workbook with the same name as another open workbook or add-in. Choose a different name, or close the other workbook or add-in before saving.
Is it possible to create and save multiple Excel worksheets within one Excel workbook in X++?
Thanks again to Jan for responsing
After reviewing the SysDataExcelCOM class, there is a CreateWorkbook method which creates the additional worksheets for the Excel Data Definition export. After creating a new similar class method and also declaring my own set of defined names (#define.ExampleExcelWorksheetName('abcSheet') for the Excel Worksheets, I was then able to create the Excel Workbook with multiple worksheets. Then save (SysExcelWorkbook.saveAs) after all of the necessary sheets are created first, rather than open the saved Workboook then adding worksheets per new class method.
Within the other class methods where data is intended to write to the Worksheets, I opened the Workbook created by the new method similar to CreateWorkbook (sysExcelWorkbooks.open(yourExcelFile), then refer to each Worksheet using (sysExcelWorksheet.itemByName) to write the data to the specific Worksheet, then save.
excelApplication = SysExcelApplication::construct();
excelWorkbooks = excelApplication.workbooks();
excelWorkbooks.open(fileNameSave);
excelWorkbook = excelWorkbooks.item(1);
//Add styles and fonts
excelStyles = excelWorkbook.styles();
excelStyle = excelStyles.add("Header");
excelFont = excelStyle.font();
excelFont.bold(true);
excelWorksheets = excelWorkbook.worksheets();
excelWorksheet = excelWorksheets.itemFromName(#declared name of your worksheet);
// Begin Header Row
excelWorksheet.cells().item(1,1).value("value of your choice");
excelWorksheet.cells().item(1,2).value("value of your choice");
excelWorksheet.rows().item(1).style("Header");
excelWorksheet.name("Rename your declared worksheet name or use current name here");
excelCells = excelWorksheet.cells();
excelCells.range('A:B').numberFormat('#');
//Find you data to write to Excel Worksheet here
excelWorksheet.columns().autoFit();
excelApplication.displayAlerts(false);
excelWorkbook.saveAs(fileNameSave);
excelWorkbook.comObject().save();
excelWorkbook.saved(true);
excelApplication.quit();
Going this route worked well for me.
This is maybe not a direct answer to your question, but might give you another perspective on creating Excel files.
I tend to use XML and XSLT to create Excel files. You can easily create what you want in Excel and then save the Excel file as XML and then you can apply some XSLT that reads data from another XML file and puts it into the Excel file you want.
You can find a post concerning this topic on my blog : Using C#, XML and XSLT to create Excel files
There I create an XML file containing Items and transform that into an Excel file.
Check the idendity of the Excel COM service. See what others have done.
Related
I open an Excel workbook with a click on a button in another program which works pretty fine. Now I would like to store the data of the workbook in a collection without saving the excel file. The name of the workbook changes dynamically. How can I save the data of the workbook in a collection?
I've already tried to use an Action stage with the Excel VBO Business Object and 'Get Worksheet as Collection' Action but as I don't know what to enter as a Workbook name nothing happens.
To do what you want is like this:
The MS Excel VBO action "Attach" will attach to whatever instance of Excel you happen to be running, regardless of any workbook names. It will output the "handle" data item that you can then use with the "Get Worksheet as Collection" action.
So this way you don't need to save the file. However, be aware that this will not work if you have more than one instance of Excel running.
Is it possible to set a Unique GUID Property of each the excel workbook sheet. So that even when user renames the sheet I could be able to retrive the correct sheet programmatically via sheet Unique GUID.
We are creating a plugin which should be able to point to correct excel sheet even when user renames it to a different value.
Could not find any handle or property in excel sheet object.
Microsoft.Office.Interop.Excel.Worksheet sheet1 in ActiveWorkbook.Worksheets
This is a long shot but I'd set the (Name) field for the worksheet in Excel directly (from the VBA Editor) ...
... and see if that is then accessible from the CodeName field in the interop properties for the workbook in C# implementation.
If you're not familiar with how to get to that editor, in Excel, press Alt + F11
Obviously after you've made that change, save the workbook and then try again from your C# project.
That field is for that exact purpose but it's a design time field only, you can't set it at run time. It's used so if the name of the sheet changes or it's index changes, you can still reference it via the technical name (CodeName).
I'd be interested to see how that goes and if it then works for you.
I have created an application already in excel where one sheet (Sheet 1) acts as a database that stores data for thousands of records. Another sheet (Sheet 2) acts as a form where users selects a record > the form gets populated with data from Sheet 1 > user updates fields > and then save it back to Sheet 1.
This has been working great, except now we need to be able to have multiple users working in the same worksheet making updates at the same time. I cannot use the Excel Share Workbook functionality because many parts of my VBA code require unprotecting and reprotecting certain sheets and that functionality doesn't work on shared workbooks.
So now, I have split the workbook into two separate workbooks. Workbook 1 has the data in it and is saved as a .csv file. Workbook 2 is just a form that has a connection to workbook 1 via the get External Data functionality already in Excel. I can import data from the .csv file without a problem, but the only way I am finding to export the data back into the .csv file is through doing a save as. This causes a problem because it turns my multi-sheet macro enabled workbook into a csv file after the save.
Is there any other way I can update the csv file without saving my workbook as a .csv?
I don't need any code done, I just need ideas more than anything. This is already a fairly large application and due to security restrictions I have already been told I cannot use a SQL server connection and we do not have access to Access to use an Access database. So solution has to stay inside excel/text files?
I recently made an Excel workbook (with the help of Stackoverflow) where I have a regular input of data (each entry is one row with different columns). I then have a macro that extracts the data from a specified row to a different sheet and saves this sheet as a .PDF.
That way, I can extract specific data from this Excel "database" to a readable pdf. I do this because I need a paper version from specific entries.
For a different project I need to implement the same principle. The only difference is that I need to work with an .mdb file where the data is stored, instead of an Excel workbook.
Is there a way I can reuse my code from Excel or is it now a completely different story?
Thank you for the advice.
You can link your excel workbook to your Access tables. On the "DATA" ribbon there is a section for "External Data".
Once you've got the Access data displayed on one of your worksheets, you should be able to adapt your existing code accordingly.
From Microsoft:
Connect an Access database to your workbook
We are trying to generate MS Excel workbook using OOXML and populate data using SSIS.
We are able to generate Workbook and sheets, also able to create columns and insert data in the Header cell. We can also populate data using SSIS.
But the Sheet (DocumentFormat.OpenXml.Spreadsheet.Sheet) and all cells (DocumentFormat.OpenXml.Spreadsheet.Cell) becomes OpenXmlUnknownElement. So we are not able to read sheet / cell using following code: Sheet sheet = workbookPart.Workbook.Descendants<Sheet>().Where(s => s.Name == "Sheet1").SingleOrDefault<Sheet>();
We are able to read the same file if we first open it using MS Excel and save. Does anyone know how to resolve this?
You probably forgot to give your sheet a name. You can see this by using
Sheet sheet = workbookPart.Workbook.Descendants<Sheet>().FirstOrDefault
and you'll see that your sheet name is either undefined or garbage text.
If that does not help. Create a simple document in code save it in OOXML and open it in a xml viewer. then make a copy open it in Excel and save it and see the difference in xml. That is often a good start seeing what excel has added by default to the document.
Excel is very tolerant of things that you have done wrong when creating the document in code, and magically fix them when you open the document again.
A bad hack would be using interop to open the document saving it again in code. wich would fix everything for you.
Workbook wrkbk = app.Workbooks.Open(#"c:\del.xls");
wrkbk.Save();
wrkbk.Close();