I found a problem while using the set_value method. I wrote the simplest possible code to exclude my mistakes.
When I read some cells and then write them back to sheet using set_value while:
any filters are active in xlsx file,
2 or more columns are get/set,
some of the cells are corrupted (they are empty or contain junk like #N/D!). When I disable filtering in worksheet or in program before using set_value, everything works fine. I can't find any info about this specific problem in google, am I doing something really stupid?
Excel.Workbooks workbooks;
Excel.Workbook workbook = null;
Excel.Worksheet sheet = null;
Excel.Application excelApplication;
excelApplication = new Excel.Application();
excelApplication.Visible = false;
workbooks = excelApplication.Workbooks;
workbook = workbooks.OpenXML(file);
sheet = workbook.Sheets[1];
Excel.Range excelRangeR = sheet.UsedRange;
object[,] valueArrayR = (object[,])excelRangeR.get_Value(Excel.XlRangeValueDataType.xlRangeValueDefault);
//if uncomment line below (or manualy disable filters in XLSX file), set_value works fine
//sheet.AutoFilterMode = false;
excelRangeR.set_Value(Excel.XlRangeValueDataType.xlRangeValueDefault, valueArrayR);
workbook.Save();
workbook.Close();
System.Runtime.InteropServices.Marshal.ReleaseComObject(excelRangeR);
System.Runtime.InteropServices.Marshal.ReleaseComObject(sheet);
System.Runtime.InteropServices.Marshal.ReleaseComObject(workbook);
System.Runtime.InteropServices.Marshal.ReleaseComObject(workbooks);
excelApplication.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(excelApplication);
You can leave the filters on, but if there is an active filter on the sheet, that has to be removed before setting the value of the cells. I think what is happening is that when you set the object[,] variable, it's populating the array with all the data in the range, including the rows that are not visible, but when you set the value of the range to the object[,] array, it only overwrites the visible rows. It's either that or vice versa.
Sorry if this code is incorrect. I'm just guessing at the C# Interop syntax. I don't use it all that often.
if (sheet.get_FilterMode()) {
sheet.ShowAllData();
}
Unfortunately there isn't an easy way to save the current value of the worksheet filters, so it would be difficult if you need to be able to restore the filters after the paste operation.
Related
now I am working on a project using c# to built a console application, which is to add more functions based on Excel. For example, SUM() is already built in the Excel. I try to add other functions that could work as the same way as SUM().(once the user click on the function button, the function will showed in the excel's active cell with parameters that need to be passed. If user click on like cell B1:A1, the content in B1:A1 will show as one of the parameters in this function. Just work exactly same as how SUM() function work in excel). My question is, if there is a way that I could input the function into the cell without creating a new worksheet. Every time I run the program, it will show a excel itself. And all the function will showed in this excel. So I don't want to create another excel, instead I want to use this excel to achieve all the functions.
this is what I get:
//export is a button, user could click on this button, and the corresponding function should show in the cell. (should in the active cell, but I will figure it out later).
//this give me a new worksheet
//because every time I run the program, the program showed me a worksheet. I want to use this worksheet.
private void export_Click(object sender, EventArgs e)
{
Microsoft.Office.Interop.Excel.Application xla = new Microsoft.Office.Interop.Excel.Application();
Workbook wb = xla.Workbooks.Add(XlSheetType.xlWorksheet);
Worksheet ws = (Worksheet)xla.ActiveSheet;
xla.Visible = true;
//index from 1
ws.Cells[2, 1] = trans1.Text;
ws.Cells[3, 1] = trans2.Text;
ws.Cells[4, 1] = trans3.Text;
}
I don't know if I express my question clearly. My English is not that good, but feel free to ask me.
very appreciate for helps!
I get it! it is really easy.
Excel.Application xlapp = (Excel.Application)ExcelDnaUtil.Application;
Excel.Workbook wbook = xlapp.ActiveWorkbook;
Excel.Worksheet wsheet = wbook.ActiveSheet;
In Excel 2013 I can't add a Worksheet after creating the workbook. My C#-Program did this, but if I set the Application on Visible = true, there is no Worksheet in it. My Program can rename Sheets, copy Sheets, but can't Show me them.
After all is done in my program, it need to be saved, but it doesnt work, because there is nothing displayed what can be saved!
This is my code:
Excel.Application appversion = new Excel.Application();
appversion.Visible = true;
Excel.Workbook dataBook = excelApp.Workbooks.Add();
dataSheet = dataBook.Worksheets[1]; // <- this sheet is not visible
dataSheet.Visible = Excel.XlSheetVisibility.xlSheetVisible; // does not work
dataSheet.Name = Seiten[0]; // but my program continues
After adding the workbook Excel starts with this:
workbook without sheet
But where is the default sheet? Without that, I can't save anything. In Excel 2010 all Sheets I need appear and I can see how my program works.
I am working on a project that runs MySQL queries on DB. I need to feed out the results to a excel sheet that I will be generating on the fly. I had started the code, using msdn tutorials as well as information I found on stackoverflow, however running the application leaves me with
"Object reference not set to an instance of an object."
At this point I just have the basic code started as I wanted to make this work before I started creating the entire spreadsheet in the code.
var excelApp = new Excel.Application();
excelApp.Visible = true;
Excel.Worksheet workSheet = (Excel.Worksheet)excelApp.ActiveSheet;
((Excel.Range)workSheet.Cells[1, 1]).Value = "Print Date:";
If I can provide any more info just ask. I greatly appreciate any information or insight you can provide me with!
I'd say that workSheet is being set to null as excelApp.ActiveSheet doesn't exist yet.
Here's some code that'll create a worksheet object you can use...
var application = new Application();
var workbooks = application.Workbooks;
var workbook = workbooks.Add(XlWBATemplate.xlWBATWorksheet);
var worksheets = (Sheets)workbook.Worksheets;
var worksheet = worksheets[1];
A few things to note when working with Excel:
Release every object with System.Runtime.InteropServices.Marshal.ReleaseComObject(object) when you're finished with it. If you don't, Excel won't exit when you're done.
Don't use double-dot references (i.e., object1.object2.value). If you do you can't release it properly as above.
Indexes always start from 1, not 0 (in my experience anyway).
The reason you get that error is, you have not created any worksheets in the Application.
Try doing this.
Excel.Worksheet newWorksheet;
newWorksheet = (Excel.Worksheet)excelApp.Worksheets.Add();
Is there a way to save changes to an excel spreadsheet through the excel interop (in this case I am adding a worksheet to it) without having it prompt the user if they want to overwrite the existing file with the changes. I do not want the user to even see the spreadsheet open in my application so having a message box popping up asking them if they want to overwrite the file seems very out of place and possibly confusing to the user.
I am using the workbook.SaveAs(fileloaction) method.
Here is where I am initializing the COM reference objects for the excel interop.
private Excel.Application app = null;
private Excel.Workbook workbook = null;
public Excel.Workbook Workbook
{
get { return workbook; }
set { workbook = value; }
}
private Excel.Worksheet worksheet = null;
private Excel.Range workSheet_range = null;
Below is the code I am using to close/save the excel file. The workbook.close() method line is the one that is reportedly throwing the unhandled exception.
workbook.Close(true, startForm.excelFileLocation, Missing.Value);
Marshal.ReleaseComObject(app);
app = null;
System.GC.Collect();
Basically, all you need is ExcelApp.DisplayAlerts = False - Here's how I do it, though:
ExcelApp.DisplayAlerts = False
ExcelWorkbook.Close(SaveChanges:=True, Filename:=CurDir & FileToSave)
Hope this helps
Only this code will Require for stop override alert or Template already in use
ExcelApp.DisplayAlerts = False
I know this is an old post, but I wanted to share a way to make this work without causing possible frustration in the future.
First what I do not like about using: ExcelApp.DisplayAlerts = False
Setting this flag will set this property on the excel file, not just in your program. This means that if a user makes changes to the file and closes it (by clicking the X), they will not be prompted to save the file and will cause frustration later. It will also disable any other prompts excel would typically post.
I like checking if the file exists before saving it:
if (File.Exists(SaveAsName))
{
File.Delete(SaveAsName);
}
Dim objworkbook As Excel.Workbook
objworkbook = objExcelAppDataSheet.Workbooks.Add(strTemplatePath)
Dim sheet_new As Excel.Worksheet
sheet_new = objworkbook1.Sheets.Add()
sheet_new.Name = objworksheet.Name
objworksheet.Cells.Range("A1", "EX150").Copy()
sheet_new.Paste()
Clipboard.Clear()
objworkbook.Close(SaveChanges:=False)
objExcelAppDataSheet is the excel application's object and strTemplatePath is the path of the excel file...
This excel file is like a template that i am using in my application. In this file some cells are merged. After copying to the new sheet the formatting of the sheet does not remain same. Columns sizes are changing. Why this problems occurs??
Is this MS office versions issue??
The below example assumes you are copying from your source (template) workbook to another workbook. Your question isn't clear on that point, so this is what I assumed.
Dim strTemplatePath As String = "...your source workbook path and name..."
Dim strDestinationPath As String = "...your destination workbook path and name..."
Dim sourceWorkBook As Excel.Workbook
Dim destWorkBook As Excel.Workbook
sourceWorkBook = objExcelAppDataSheet.Workbooks.Add(strTemplatePath)
destWorkBook = objExcelAppDataSheet.Workbooks.Add(strDestinationPath)
Dim mySourceSheetName As String = "...your source worksheet name..."
Dim sourceWorkSheet As Excel.Worksheet
sourceWorkSheet = sourceWorkBook.Sheets(mySourceSheetName)
//Copies the source worksheet to the destination workbook, places it after the last
//sheet in the destination workbook.
sourceWorkSheet.Copy(, destWorkBook.Sheets(destWorkBook.Sheets.Count))
destWorkBook.SaveAs(strDestinationPath)
destWorkBook.Close()
sourceWorkBook.Close()
If you are just copying and pasting in the source workbook ( not using a different destination ) you can just remove the destination workbook portions of the code. Then your Copy statement would look like this:
sourceWorkSheet.Copy(, sourceWorkBook.Sheets(sourceWorkBook.Sheets.Count))
This will place the source sheet after the last sheet in your source workbook.
If you want to duplicate the formatting that includes column widths, row heights, cell merging, etc. in your new sheet, you need to copy the entire sheet.
If you don't want all of the data on the source sheet, but you still want the column widths, etc., you must first copy the entire sheet; then clear the newly copied sheet. This will remove the data, but not the formatting. After that, then you can copy just the range of cells that has the data you want.
Have you tried to copy the whole sheet instead of just some cells like in this example.