switch row/column of chart using c# excel interop - c#

I'm currently working on a Programm which creates reports using Excel Interop. Therefore I intend to create a Line Chart as followed:
As one can see here I have a clear development of num and denom in relation to Milestones. When I select my values as chartRange manually in Excel I recieve this Diagramm. However, when do it programmatically (select exactly the same range) I get this:
Well, you can see the data selected. Excel (or something I don't know about) fails to recognize the Milestones row as axis. When I right click on the Diagramm --> select data --> Change rows/columns I get my right Chart.
Now does anybody know an order to switch those rows/columns or some way to define ranges for each of the axis?
I attached the relevant part of my code here:
Excel.Application myExcelApplication;
Excel.Workbook myExcelWorkbook;
object misValue = System.Reflection.Missing.Value;
myExcelApplication = null;
myExcelApplication = new Excel.Application();
myExcelApplication.Visible = true;
myExcelApplication.ScreenUpdating = true;
myExcelWorkbook = (Excel.Workbook)(myExcelApplication.Workbooks.Add(misValue));
Excel.Worksheet newWorksheet;
newWorksheet = (Excel.Worksheet)myExcelApplication.Worksheets.Add();
newWorksheet.Name = requestedVehicles[m];
newWorksheet = (Excel.Worksheet)myExcelWorkbook.ActiveSheet;
Excel.Range chartRange = myExcelApplication.get_Range("B2", endrange + 4);
Excel.ChartObjects xlCharts = (Excel.ChartObjects)newWorksheet.ChartObjects(Type.Missing);
Excel.ChartObject myChart = (Excel.ChartObject)xlCharts.Add(100, 20, 500, 400);
Excel.Chart chartPage = myChart.Chart;
chartPage.HasTitle = true;
chartPage.ChartTitle.Text = "num/denom";
chartPage.SetSourceData(chartRange, Excel.XlRowCol.xlColumns);
chartPage.ChartType = Excel.XlChartType.xlXYScatterLines;
Thanks in advance,
Andy

I solved it myself due to this post I've stumbled across:
https://www.codeproject.com/questions/870177/csharp-excel-chart-x-axis-category-labels
The Problem was that the upper left cell of my defined range wasn't empty.. so Excel assumed it was supposed to be a data series.

hmmm, if the proposed solution does not work for all, this is how you can do it directly from the interop; use the method ChartWizard(), the parameter PlotBy does the trick.
This is how I use it:
wsChart.ChartWizard(Type.Missing, Type.Missing, Type.Missing, Excel.XlRowCol.xlRows, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
Here is the doc:
https://learn.microsoft.com/en-us/dotnet/api/microsoft.office.interop.excel._chart.chartwizard?f1url=https%3A%2F%2Fmsdn.microsoft.com%2Fquery%2Fdev15.query%3FappId%3DDev15IDEF1%26l%3DEN-US%26k%3Dk(Microsoft.Office.Interop.Excel._Chart.ChartWizard);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.6);k(DevLang-csharp)%26rd%3Dtrue&view=excel-pia

Related

C# Programatically change cell format of all Excel cells to General

As part of an ETL process I am importing data from a variety of different Excel files into a database. Before this happens I need to be able to change the cell format of all cells in an excel worksheet to be in the "General" format.
I have made a start but I'm afraid I dont know how to progress after this:
using Excel = Microsoft.Office.Interop.Excel;
.
.
.
String FilePath = "Code to get file location from database"
String SheetName = "Code to get SheetName from database"
Excel.Application MyApp = new Excel.Application();
MyApp.Visible = false;
Excel.Workbook myWorkbook = MyApp.Workbooks.Open(FilePath,Type.Missing, Type.Missing, Type.Missing, Type.Missing,Type.Missing, Type.Missing, Type.Missing, Type.Missing,Type.Missing, Type.Missing, Type.Missing, Type.Missing,Type.Missing, Type.Missing);
//Code here to convert all rows to data type of general and then save
MyApp.Workbooks.Close();
Any help on this would be greatly appreciated
You can use Range.NumberFormat property:
var myWorksheet = (Excel.Worksheet)myWorkbook.Worksheets[1];
myWorksheet.Cells.NumberFormat = "General";
Please note that this may cause problems if your sheet contains date values.

Searching date string in file excel

I'm working with an excel file and I'm trying to find the position(address) of the cells with date value like "16/02/2015" as content. In order to do this with windows Forms application I use a datetimepicker. My code is as following:
// Firstly I want a string like 16/02/2015 inserted in the datetimepicker
string date = DateTimePicker1.Value.ToString().Substring(0,10);
List<string> Testsdone = new List<string>();
Excel.Application xlApp;
Excel.Workbook xlWorkBook;
Excel.Worksheet xlWorkSheet;
object misValue = System.Reflection.Missing.Value;
xlApp = new Excel.Application();
xlWorkBook = xlApp.Workbooks.Open(file_opened, 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);
xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(4);
Excel.Range currentFind = null;
Excel.Range firstFind = null;
Excel.Range tests = xlWorkSheet.get_Range("K13", "K2295");
currentFind = tests.Find(date);
.....
I have exactly the same content "16/02/2015" written in my excel file, but the currectFind always shows null! I have no idea why the two "16/02/2015" are different. Anybody got an idea? thanks!
Well after some investigation I found that the problem is caused by the Find function
currentFind = tests.Find(date);
which for unknown reason failed to find the date. From another post
how to Search in excel file I got this method, that I changed this into:
currentFind = xlworkSheet.Cells.Find(date, Type.Missing, Microsoft.Office.Interop.Excel.XlFindLookIn.xlValues, Microsoft.Office.Interop.Excel.XlLookAt.xlWhole, Microsoft.Office.Interop.Excel.XlSearchOrder.xlByRows,Microsoft.Office.Interop.Excel.XlSearchDirection.xlNext, false,Type.Missing, Type.Missing);
And it works. But I still have no idea why the Excel.Range.Find fails and Excel.workersheet.Cells.Find works

Excel worksheet get item

I have a problem with Excel worksheet. I am trying to create an Excel file with c#.
This code works and runs correctly on my computer but in other computers get an error at last line:
Excel.Application xlApp;
Excel.Workbook xlWorkBook;
Excel.Worksheet xlWorkSheetInvoice;
Excel.Worksheet xlWorkSheetInvoiceLine;
object misValue = System.Reflection.Missing.Value;
xlApp = new Microsoft.Office.Interop.Excel.Application();
xlWorkBook = xlApp.Workbooks.Add(misValue);
xlWorkSheetInvoice = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
xlWorkSheetInvoiceLine = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(2);
System.Runtime.InteropServices.COMException (0x8002000B): Invalid index. (Exception from HRESULT: 0x8002000B (DISP_E_BADINDEX))
at Microsoft.Office.Interop.Excel.Sheets.get_Item(Object Index)
I executed a sample application with similar code on a machine with Excel 2013 and it fails at the same line of code you mentioned. By default Excel 2013 application opens up with a single worksheet ("Sheet1") so you would have to modify the code accordingly
DISP_E_BADINDEX seems to suggest the number of worksheets is less on the other computers. Build in a check to see if the number of worksheets is less than 2 before using get_Item().
i have created new sheet and assigned xlWorkSheetInvoice and xlWorkSheetInvoiceLine to solve it.
var xlSheets = xlWorkBook.Sheets as Excel.Sheets;
var xlNewSheet = (Excel.Worksheet)xlSheets.Add(xlSheets[1], Type.Missing, Type.Missing, Type.Missing);
var xlNewSheet2= (Excel.Worksheet)xlSheets.Add(xlSheets[2], Type.Missing, Type.Missing, Type.Missing);
xlWorkSheetInvoice = xlNewSheet;
xlWorkSheetInvoiceLine = xlNewSheet2;
xlWorkSheetInvoice = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
xlWorkSheetInvoiceLine = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(2);

Hide Excel 2013 while programmatic change a workbook

A really good new feature of Excel 2013 is that it cannot forced to show more than one Excel workbook in one application. This seems the cause of my Problem:
If I open an Excel workbook programmatically using c# and interop Excel 2013 starts with a new application window. I can working with the workbook in code without problems but I want to hide the application.
Using
Excel.Application excelApp = new Excel.Application();
......
excelApp.Workbooks.Open(...);
excelApp.Visible = false;
hides the application window after showing it. Is there a way to stop showing the application as in Excel 2010 or earlier Version?
In my Excel 2013, using excelApp = new Excel.Application doesn't show any window.
May it be some VBA code in opened workbook which displays window?
So I know the question is old but I needed an answer and none of the given ones worked for me. I ended up just setting Visible to false when initializing to avoid the window flashing open before hiding.
Excel.Application excelApp = new Excel.Application() { Visible = false };
Hide Excel application your code has launched, before opening any Workbook :
Excel.Application excel = new Excel.Application();
excel.Visible = false;
[...]
Excel.Workbook workbook;
workbook = excel.Workbooks.Open(...);
You should always put the Visible into try/catch-block
Excel.Application xlsApp = new Excel.Application();
try
{
// Must be surrounded by try catch to work.
// http://naimishpandya.wordpress.com/2010/12/31/hide-power-point-application-window-in-net-office-automation/
xlsApp.Visible = false;
xlsApp.DisplayAlerts = false;
}
catch (Exception e)
{
Console.WriteLine("-------Error hiding the application-------");
Console.WriteLine("Occured error might be: " + e.StackTrace);
}
Excel.Workbook workbook;
workbook = xlsApp.Workbooks.Open(File, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing);

Writing To Excel Files in C#

I have a Excel File, i am able to read single row from "Excel file" Cell by Cell and store it in a ArrayList.
ExcelRange reads one row at a time , stores it into ArrayList (arrForValues).
ExcelRange = ExcelWorkSheet.get_Range("A"+rowNumber,columnMaxName+rowNumber );
items = (object[,])ExcelRange.Value2;
for (int i = 1; i <= nColumn; i++)
{
arrForValues.Add(items[1, i]);
}
I want to write row to another Excel file.There is some condition which needs to be satisfied for "particular Row" to get selected for writing.
Is there any way i can write complete ArrayList("Single Row") to ExcelFile instead of Cell By Cell Wrinting.
Thanks in Advance.
You can write whole array of objects by using range's set_value method
Here is example:
class Program
{
static void Main(string[] args)
{
string file = AppDomain.CurrentDomain.BaseDirectory + "SetArrayToExcel.xlsx";
Excel.Application excelApp = new Excel.Application();
excelApp.Visible = true;
Excel.Workbook wb = excelApp.Workbooks.Open(file, Type.Missing, Type.Missing
, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing
, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing
, Type.Missing, Type.Missing);
object[,] testTable = new object[2, 2]{{"6-Feb-10", 0.1}, {"26-Mar-10", 1.2}};
Excel.Worksheet ws = wb.ActiveSheet as Excel.Worksheet;
Excel.Range rng = ws.get_Range("rngSetValue", Type.Missing);
//rng.Value2 = testTable;
rng.set_Value(Type.Missing, testTable);
}
}
I highly recommend just getting FlexCel. It's fairly cheap and it has methods for copying rows and columns.
EDIT: I see that you mean to copy between workbooks. It's still easier with FlexCel than COM or the Interop stuff.
I do some writing to Excel in some code I have. The only way I have found to do it is with a foreach to iterate through my list of values and using an indexer to keep track of what cell it is going into. You might investigate the Range class and the Cells property:
http://msdn.microsoft.com/en-US/library/microsoft.office.tools.excel.namedrange.cells(v=vs.80).aspx
It didn't work for what I am doing but it might for you.
Another alternative would be to merge the cells in a range, build a string of all the values in your array and set the merged range value equal to that string but that might not be what you want.

Categories