Use C# to duplicate a chart in Excel - c#

I've got a spreadsheet that contains a template chart. In the past I've used the copy/paste functionality, but from time to time I run into an error where I copy something onto the clipboard at the same time my code is and I'd like to avoid that. So I looked into the Duplicate method. Should the code below work? The chart does get duplicated fine.
The problem I'm having is that I'm not sure how to get the chart object after it has been duplicated. On this line:
ChartObject chart = (ChartObject)o;
I get this error: Unable to cast COM object of type 'System.__ComObject' to interface type 'Microsoft.Office.Interop.Excel.ChartObject'. Here is my code:
string file = #"D:\test.xlsx";
Microsoft.Office.Interop.Excel.Application app = new Microsoft.Office.Interop.Excel.Application();
app.Visible = true;
ApplicationClass temp = new ApplicationClass();
Microsoft.Office.Interop.Excel.Workbook oBook;
Microsoft.Office.Interop.Excel.Worksheet oSheet;
oBook = app.Workbooks.Open(file, 0, false, 1, "", "", true, XlPlatform.xlWindows, "\t", false, false, 0, true, true, XlCorruptLoad.xlNormalLoad);
oSheet = oBook.Worksheets["template"] as Worksheet;
object o = ((ChartObject)oSheet.ChartObjects("template")).Duplicate();
ChartObject chart = (ChartObject)o;
chart.Name = "TEST";
Can I get the count of ChartObjects? If I were doing it in a macro I could use this line to get the last chart
oSheet.ChartObjects(oSheet.ChartObjects.Count)
Any suggestions? I sincerely appreciate any help.
Thanks,
Nick
In the event anyone is interested in how I ended up doing this. Assuming you have a worksheet named "template" and on that sheet you also have a chart named "template."
Microsoft.Office.Interop.Excel.Worksheet oTemplate = oBook.Worksheets["template"] as Worksheet;
Microsoft.Office.Interop.Excel.Worksheet oOutput = oBook.Worksheets["output"] as Worksheet;
// duplicate template chart
ChartObject chartTemplate = (ChartObject)oTemplate.ChartObjects("template");
object o = chartTemplate.Duplicate();
ChartObject chart = (ChartObject)oTemplate.ChartObjects(GetChartCount(oTemplate));
public static int GetChartCount(Microsoft.Office.Interop.Excel.Worksheet oSheet)
{
int x = 0;
foreach (Microsoft.Office.Interop.Excel.Shape s in oSheet.Shapes)
{
if (s.HasChart == MsoTriState.msoTrue)
x++;
}
return x;
}
Maybe not the best way, but it works.

Related

Microsoft.Office.Interop.Excel cells remain null after setting them

I have an application in which I'm trying to write to an Excel file. It doesn't seem to be working.
Here is my code:
using System;
using System.Drawing;
using Microsoft.Office.Interop.Excel;
namespace Image2Excel {
class Engine {
public static void go(string imageFilename, string excelFilename = null) {
//Image img = Image.FromFile(imageFilename);
Bitmap btm = (Bitmap)Bitmap.FromFile(imageFilename, false);
Image img = Image.FromFile(imageFilename, false);
if (btm != null) {
Color[][] colorArray = new Color[btm.Width][];
for (int x = 0; x < btm.Width; x++) {
colorArray[x] = new Color[btm.Height];
for (int y = 0; y < btm.Height; y++) {
colorArray[x][y] = btm.GetPixel(x, y);
}
}
var excel = new Microsoft.Office.Interop.Excel.Application();
var workbook = excel.Workbooks.Add(Type.Missing);
var worksheet = (Microsoft.Office.Interop.Excel.Worksheet)workbook.ActiveSheet;
worksheet.Name = "sheet1";
worksheet.Cells[1,1] = "top left";
worksheet.Cells[1,2] = "top right";
worksheet.Cells[2,1] = "bottom left";
worksheet.Cells[2,2] = "bottom right";
workbook.SaveAs("temp.xlsx");
workbook.Close();
excel.Quit();
Marshal.ReleaseComObject(worksheet);
Marshal.ReleaseComObject(workbook);
Marshal.ReleaseComObject(excel);
}
}
}
}
I'm trying to write some text to the first 4 cells in the spreadsheet. It's not working. When I open the file, I see nothing in the cells.
I do see that the sheet name is set to what I set it to so I know it's writing to the files.
One thing I noticed when I debug is that worksheet.Cells[1,1] is null after I set it. I'm wondering if I need to set the cell to an object before writing to it. But I'm not sure how. I don't seem to be able to do this:
worksheet.Cells[1,1] = new Microsoft.Office.Interop.Excel.Cell();
Hovering over Cells tells me it's a Range object, but I'm not sure how to set it to a range either. I tried this:
worksheet.Range["A1"].Value = "hello";
worksheet.Range["A1"].Value2 = "hello";
...but those don't work either. worksheet.Range remains null just like worksheet.Cells.
How can I make sure worksheet.Cells[1,1] or worksheet.Range["A1"] is set to an object that will take a string value? Thanks.
You can find my application on github: https://github.com/gibran-shah/Image2Excel
I'm using Microsoft.Office.Interop.Excel version 15.0.4795.1000.
I have Excel 2010 installed on my computer.
I haven't tried yours but could you try these methods? it worked for me.
1st method with Worksheets.Cells
// CREATE EXCEL OBJECTS.
Excel.Application xlApp;
Excel.Workbook xlWB;
Excel.Worksheet xlWS;
xlApp = new Excel.Application();
// Specify the path to the excel file
xlWB= xlApp.Workbooks.Open("path/to/xlFile.xls");
// Choose the sheet you want to open
xlWS = xlWB.Worksheets["Sheet1"];
// Write on the single cell
xlWS.Cells["1", "D"] = "Example";
// Save the change and quit
xlWB.Close(true);
xlApp.Quit();
2nd method with Worksheets.get_Range()
// CREATE EXCEL OBJECTS.
Excel.Application xlApp;
Excel.Workbook xlWB;
Excel.Worksheet xlWS;
xlApp = new Excel.Application();
// Specify the path to the excel file
xlWB= xlApp.Workbooks.Open("path/to/xlFile.xls");
// Choose the sheet you want to open
xlWS = xlWB.Worksheets["Sheet1"];
// Write on the range of cells
xlWS.get_Range["A3", "D5"] = "Example";
// Save the change and quit
xlWB.Close(true);
xlApp.Quit();

How to read cell values that are dynamically generated using macros in c#?

I have an excel file in which some cell values are generating dynamically using macro.
File is also read-only.
I have to read these dynamically generated values using c# code.
Use following macro code to generate cell values:
**Sub abc()
Range("E5").Value = "string"
Range("E6").Value = 2
End Sub**
Thank You...!
Check if you need to connect to already opened excel file.
If you use excelApp.Workbooks.Open, it is not reflecting sheet data updated by macros.
Instead, try BindToMoniker method as follows:
private void btnGetXLSValue_Click(object sender, EventArgs e)
{
object _row = 5;
object _column = 5;
Excel.Application excelApp = new Excel.Application();
excelApp.Visible = false;
excelApp.ScreenUpdating = false;
excelApp.DisplayAlerts = false;
Microsoft.Office.Interop.Excel.Workbook excelWorkbook ;//= excelApp.Workbooks.Open(#"C:\July.xlsm", 0, false, 5, "", "", false, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "", true, false, 0, true, false, false);
//Get a reference to the Workbook object by using a file moniker.
//The xls was saved earlier with this file name.
excelWorkbook = (Excel.Workbook)System.Runtime.InteropServices.Marshal.BindToMoniker(#"C:\July.xlsm");
Microsoft.Office.Interop.Excel.Sheets excelSheets = excelWorkbook.Worksheets;
string currentSheet = "July 2015";
Microsoft.Office.Interop.Excel.Worksheet excelWorksheet = (Microsoft.Office.Interop.Excel.Worksheet)excelSheets.get_Item(currentSheet);
Microsoft.Office.Interop.Excel.Range range = (Microsoft.Office.Interop.Excel.Range)excelWorksheet.UsedRange;
string sValue = (range.Cells[_row, _column] as Microsoft.Office.Interop.Excel.Range).Value2.ToString();
//string sValue = (range.Cells[_row, _column] as Microsoft.Office.Interop.Excel.Range).get_Value(range).ToString();
MessageBox.Show(sValue);
}

How to open the corresponding excel sheet in a workbook using c#

My code opens the first sheet of an excel. My target is to open the sheet selected in combobox. Do anyone can help me to find solution:
My Code:
string currsheet = comboBox1.SelectedItem.ToString();
Microsoft.Office.Interop.Excel.Application xap = new Microsoft.Office.Interop.Excel.Application();
xap.Visible = true;
Microsoft.Office.Interop.Excel.Workbook wk = xap.Workbooks.Open(path3,0, false, 5, "", "", false, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "", true, false, 0, true, false, false);
Microsoft.Office.Interop.Excel.Sheets excelsheet = wk.Worksheets;
Microsoft.Office.Interop.Excel.Worksheet wsh = (Worksheet)excelsheet.get_Item(currsheet);
By sheet name
Microsoft.Office.Interop.Excel.Worksheet wsh = (Worksheet)excelsheet["SheetName"];
By index (starting with 1 - first sheet)
Microsoft.Office.Interop.Excel.Worksheet wsh = (Worksheet)excelsheet[1];
Just use one of those values in your combobox.
If you want to populate your combo box with available sheets, you can go throug Worksheets
foreach (Worksheet Sh in excelsheet)
{
Combobox.Items.Add(Sh.Name);
}
Then, the combobox selected value will be already a sheet name, you get by:
Microsoft.Office.Interop.Excel.Worksheet wsh = (Worksheet)excelsheet[Combobox.SelectedValue]; //I'm not sure if combobox value is got like this, but the excel part is ok.

creating excel sheet and writind data into it

I am working on writing the data into Excel sheet in c#.
I have wriiten the following code.
string excel_filename = #"C:\Users\Downloads\bookmain.xlsx";
Excel.Application excel = new Excel.Application();
excel.Visible = true;
Excel.Workbook wb = excel.Workbooks.Open(excel_filename);
Excel.Worksheet sh = wb.Sheets.Add();
sh.Name = "TestSheet";
sh.Cells[1, "A"].Value2 = "SNO";
sh.Cells[1, "B"].Value2 = "Name";
sh.Cells[1, "C"].Value2 = "ID";
for (int i = 0; i < 2; i++)
{
sh.Cells[i+2, "A"].Value2 = "1";
sh.Cells[i+2, "B"].Value2 = "A";
sh.Cells[i+2, "C"].Value2 = "1122";
}
wb.Save();
excel.Quit();
Here I have given the path of excel file that already exists and it is empty.
How to change this code that, when i give the path it should automatically check, if it exists it have to create otherwise no need to create.
Even my code also need to check sheet name, it it exist i shall directly edit it or else I need to create a new sheet.
Can any one share their response.
Thank you.
for checking existence of file :
if(!File.Exists(excel_filename))
{
//if not exists then only create:-
}
and for checking worksheet you can do like :
foreach (Sheet sheet in workbook.Sheets)
{
if (sheet.Name.equals("Test"))
{
//do something
}
}
UPDATED :
this is how it works :
Create Excel object
Excel.Application excel = new Excel.Application();
make Excel visible
excel.visible = true
add a worksheet
Excel.Worksheet sh = wb.Sheets.Add();
save it as
wb .SaveAs( #"C:\Users\Downloads\bookmain.xlsx",
Excel.XlFileFormat.xlXMLSpreadsheet, missing, missing,
false, false, Excel.XlSaveAsAccessMode.xlNoChange,
missing, missing, missing, missing, missing);

.Net Excel Interop Deleting a worksheet

I'm trying to delete a worksheet from a excel document from a .Net c# 3.5 application with the interop Excel class (for excel 2003).
I try many things like :
Worksheet worksheet = (Worksheet)workbook.Worksheets[1];
worksheet.Delete();
It's doesn't work and doesn't throw any error ...
After more than one hour looking I found the answer:
xlApp.DisplayAlerts = false;
worksheet.Delete();
xlApp.DisplayAlerts = true;
When dealing with deleting Excel Worksheets, there are two important things to know:
Excel interop counts from 1 (and not from zero), therefore, removing the second item will cause the third item to take its place!. so, the proper way to remove worksheets is from the last to the first:
// Remove LAST worksheet
MyWorkBook.Worksheets[3].Delete();
// and only then remove the second (which is the last one)
MyWorkBook.Worksheets[2].Delete();
alternatively, you can delete the second item ([2]) on the list twice, which will give you the same result.
The following line will throw exception when you only got one worksheet left:
MyWorkBook.Worksheets[1].Delete();
It is also important to note that the workbook must contain at least one worksheet; this means you cannot delete all worksheets in a workbook.
Microsoft.Office.Interop.Excel.Worksheet worksheet = Microsoft.Office.Interop.Excel.Worksheet)xlWorkBook.Worksheets[1];
worksheet.Delete();
Try to find worksheet by name:
var app = new Microsoft.Office.Interop.Excel.Application();
var workbook = app.Workbooks.Add();
((Microsoft.Office.Interop.Excel.Worksheet)workbook.Worksheets["Sheet3"]).Delete();
we can delete the work sheet like this
Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
if (xlApp == null)
{
return;
}
xlApp.DisplayAlerts = false;
string filePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
+ "\\Sample.xlsx";
Excel.Workbook xlWorkBook = xlApp.Workbooks.Open(filePath, 0, false, 5, "", "", false, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "", true, false, 0, true, false, false);
Excel.Sheets worksheets = xlWorkBook.Worksheets;
worksheets[4].Delete();
worksheets[3].Delete();
xlWorkBook.Save();
xlWorkBook.Close();
releaseObject(worksheets);
releaseObject(xlWorkBook);
releaseObject(xlApp);
and use this
static void releaseObject(object obj)
{
try
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
obj = null;
}
catch (Exception ex)
{
obj = null;
throw ex;
}
finally
{
GC.Collect();
}
}
We delete excel worksheets from a c# console application like this:
Microsoft.Office.Interop.Excel.Worksheet worksheet =
(Worksheet)workbook.Worksheets["Worksheet_Name" (or) "Countings"];
worksheet.Delete();

Categories