Returning Excel variables C# - c#

I have a Windows Forms application with 5 methods (each based off of the user clicking a button). In each method, I would like to open the same excel file the same way. However, in each method I want to select a different range on the worksheet. I tried creating a function to open the excel file rather than rewriting it 5 times...
// method to open Excel and load a the workbook based on date selected.
public Tuple<Microsoft.Office.Interop.Excel.Application, Workbook, Worksheet> openExcel()
{
Microsoft.Office.Interop.Excel.Application excelObj = new Microsoft.Office.Interop.Excel.Application();
string fileName = #"C:\Users\" + userName + #"\Documents\Visual Studio 2015\Projects\ProgramForMom\ProgramForMom\bin\Debug\Excel Files\" + frm2.year.Text + " Expenses";
Workbook wb = excelObj.Workbooks.Open(fileName, 0, false, 5, "", "", false, XlPlatform.xlWindows, "", true, false, 0, true, false, false);
wb.Activate(); // Activates file.
Worksheet ws = wb.Worksheets[frm2.month.Text];
ws.Activate();
return Tuple.Create(excelObj, wb, ws);
}
All that works fine.
I tried referenced this function in one of the methods...
var excelObj = openExcel();
Workbook wb = openExcel();
Worksheet ws = openExcel();
var cellValue = ws.Range["A1"].Value2;
and I get an error saying...
"Cannot implicitly convert type 'System.Tuple' to 'Microsoft.Office.Interop.Excel.Workbook'. An explicit conversion exists (are you missing a cast?)"
I get the same error for the worksheet. It says the same exact thing just substitutes the word worksheet in place of workbook.
Can you please explain what I have done wrong? Thank you.

var result = openExcel();
var excelObj = result.Item1;
Workbook wb = result.Item2;
Worksheet ws = result.Item3;
var cellValue = ws.Range["A1"].Value2;

You have a mismatch between the return type of your method (which is a Tuple) and the type of the variables in which you want to catch the output of openExcel
it should look more like this
Tuple<Microsoft.Office.Interop.Excel.Application, Workbook, Worksheet> allThreeInOne = openExcell();
then you can try and fiddle everything apart... OR
what you also can do is to access the value right at the point of the function call:
var excelObj = openExcel().Item1;
Workbook wb = openExcel().Item2;
Worksheet ws = openExcel().Item3;
this way you would assign exactly the matching type to the variables
EDIT:
Tha latter solution is not advisable since you would unnecessarily open the file 3 times just to get the result that you would have gotten already from the first call,as Joel Coehoorn correctly pointed out.
fiddling the tuple apart would be the way to go:
var excelObj = allThreeInOne.Item1;
Workbook wb = allThreeInOne.Item2;
Worksheet ws = allThreeInOne.Item3;

Related

C# Excel: Issue in copying worksheet from different workbook

I'm currently trying to copy a worksheet from a different workbook which i succeed by using Copy() and PasteSpecial(). However, I would like to know why the following code does not work even though many solutions online seems to use this approach.
Workbook currBook = Globals.ThisAddIn.GetActiveWorkbook();
Workbook copyBook = Globals.ThisAddIn.OpenWorkbook(Globals.ThisAddIn.Application.ActiveWorkbook.Path + #"\copyFile.xlsm", true, true);
//required worksheet
Worksheet copySheet = Globals.ThisAddIn.GetWorksheet(copyBook, "ToCopy");
copySheet.Copy(currBook.Worksheets[1]);
//close workbook
copyBook.Close();
Function used to get specific sheet:
public Excel.Worksheet GetWorksheet(Excel.Workbook book, string sheetName, bool create = false)
{
foreach (Excel.Worksheet sheet in book.Worksheets)
{
//worksheet with name found
if (sheet.Name == sheetName)
{
sheet.Activate();
return sheet;
}
}
//worksheet can't be found
if (create)
{
Excel.Worksheet sheet = book.Worksheets.Add();
sheet.Name = sheetName;
sheet.Activate();
return sheet;
}
return null;
}
There is no error from the stated code and the worksheet has been tested to exist. The program simply does not create a copy into currBook
Interestingly, I was just working on something else where this came up...
In order to specify a destination it's necessary to use Range.Copy, not Sheet.Copy:
copySheet.UsedRange.Copy(currBook.Worksheets[1].Range["A1"]);
If a destination can't be specified, then Excel puts the data in a new workbook.

c# - (Excel interop)How can I copy one worksheet to another workbook in VSTO?

I have searched a lot from the internet, but unfortunately, none of them worked.
How to copy sheets from a workbook to another workbook
,Cutting and Pasting Cell Values in Excel using C#,Error: Pastespecial method of range class failed
.
The thing is if I created the worksheet in the same workbook, the code works perfectly fine.
But if I created a new workbook, then the Paste would not work.
//copy function: copy to a new worksheet in the same workbook
var copyFromRange = oldSheet.Range[
(Excel.Range)oldSheet.Cells[1, 1],
oldSheet.Cells[firstPackageStartLine - 1, lastColIgnoreFormulas]];
copyFromRange.Copy(Type.Missing);
var copyHeaderRange = newSheet.Range[(Excel.Range)newSheet.Cells[1, 1], newSheet.Cells[firstPackageStartLine - 1, lastColIgnoreFormulas]];
copyHeaderRange.PasteSpecial(Excel.XlPasteType.xlPasteAll, Excel.XlPasteSpecialOperation.xlPasteSpecialOperationNone, false, false);
//Copy to a new workbook, won't work
var excel = new Excel.Application();
var newWorkbook = excel.Workbooks.Add(System.Reflection.Missing.Value);
var newSheet = (Excel.Worksheet)newWorkbook.Worksheets.Add();
newSheet.Name = "sheetName";
//copy function, same as above. But this won't work, PasteSpecial would throw null reference error.
//If I changed the copyHeaderRange to below, then it will throw: PasteSpecial method of Range class failed.
var copyHeaderRange = (Excel.Range)newSheet.Cells[1, 1];
//If the copyRange is defined as below, it will throw null reference error while pastespecial
var copyHeaderRange = newSheet.Range[(Excel.Range)newSheet.Cells[1, 1], newSheet.Cells[firstPackageStartLine - 1, lastColIgnoreFormulas]];
I have also tried open a new workbook instead of starting a new one, won't work . Tried activate the worksheet before copying, won't work either.
Any idea why this happens?
If there are any merged cells in the copy range -- even if they do not span beyond that range's coordinate cells -- and you're creating a new instance of Excel Application class, I think this error is expected.
Rather than newing your excel instance, can you modify to use the same instance of Excel (untested):
var newWorkbook = oldSheet.Application.Workbooks.Add(System.Reflection.Missing.Value);
var newSheet = (Excel.Worksheet)newWorkbook.Worksheets.Add();
newSheet.Name = "sheetName";

C#: Writing file to Excel issue

I am using ClosedXML to write my data into Excel. But here is the problem. When I write my data the old data gets removed and saves only data which I am calling. I know that is because of "new" and "Add" word I am using. Is there any other way I can specify to write files?
var workbook = new XLWorkbook();
var worksheet = workbook.Worksheets.Add("Common");
worksheet.Cell(2, 1).Value = "Sent";
workbook.SaveAs(#"..\..\File.xlsx");
Try this: This should work
string pathfile = #"..\..\File.xlsx";
XLWorkbook workbook = new XLWorkbook(pathfile);
IXLWorksheet worksheet = workbook.Worksheet("Common");
worksheet.Cell(2, 1).Value = "Sent";
workbook.Save();
You may be able to instantiate
var workbook = new XLWorkbook()
in global scope and then append to it in whatever method you're using.

Unable to change link in Excel workbook

I'm having problems changing a link in a workbook that contains a moved sheet.
I move two worksheets from a workbook (tempworkbook) called "Analysis Template.xlsx" into a new workbook (_wb), at which point, I then want to change the link that's in those two sheets from tempworkbook to refer to the new workbook they've just been moved into, yet my changelink code seems to have no effect, and i'm positive i've got the paths correct. Why is this? It's not returning any error, it's just when I check the link in excel itself, its still pointing to the original "Analysis Template" workbook.
As I want this to run in the background, i've disabled a few things within the application, could this be why?
_xl.Visible = false;
_xl.UserControl = true;
_xl.DisplayAlerts = false;
_xl.Interactive = false;
_xl.ScreenUpdating = false;
Microsoft.Office.Interop.Excel.Workbook tempworkbook = _xl.Workbooks.Open(System.IO.Directory.GetCurrentDirectory() + "\\Analysis Template.xlsx", 0, false, 1, "", "", false, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, 9, true, false, 0, true, false, false); //open template XLS file
Microsoft.Office.Interop.Excel.Worksheet tmp1 = (Microsoft.Office.Interop.Excel.Worksheet)tempworkbook.Sheets["Data"]; //extract 1st worksheet to move
Microsoft.Office.Interop.Excel.Worksheet tmp2 = (Microsoft.Office.Interop.Excel.Worksheet)tempworkbook.Sheets["Evaluation"]; //extract 2nd worksheet to move
tmp1.Move(Missing.Value, _wb.Sheets[7]); //move 1st worksheet into new workbook
tmp2.Move(Missing.Value, _wb.Sheets[8]); //move 2nd worksheet into new workbook
_wb.ChangeLink(tempworkbook.FullName, _wb.FullName, Microsoft.Office.Interop.Excel.XlLinkType.xlLinkTypeExcelLinks); //change link from template workbook to refer to new workbook
The documentation suggests that you probably need to do a loop over all link sources, and update them each individually.
If you were looking to debug the problem, I would strongly suggest you at least confirm that tempworkbook.FullName is the same as the output of LinkSources(_wb).
Haven't done it personally, just trying to help.

How can I determine how many worksheets there are in an Excel workbook?

thanks in advance for your help. I want to loop through all worksheets in a workbook. Unfortunately, I don't know how many worksheets there are in a given workbook. Right now I use the following technique to enumerate through all worksheets:
Excel.Worksheet xlWorkSheet1;
xlWorkSheet1 = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
Excel.Worksheet xlWorkSheet2;
xlWorkSheet2 = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(2);
Excel.Worksheet xlWorkSheet3;
xlWorkSheet3 = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(3);
Is there a method that returns the number of worksheets in a workbook?
Use Excel.Workbook and then you can use the Workbook.Sheets.Count() in a for or while loop.
The Worksheets property has a collection of the worksheets .
foreach (Excel.Worksheet xlworksheet in xlworkbook.Worksheets)
{
//xlworksheet code here
}
Or, get the count value and use a for loop.
Googling this results in either this page, or several others where you have to use VBA or C# or start mucking about in the Name Manager in Excel.
Anyone looking for a quick and dirty solution:
Open the xlsx file with 7zip and navigate to xl\worksheets.
In there you should see all the sheets, and if you select those 7zip will count them for you.
Insert a module in the workbook you want to count the total sheets of,
Then type the below code and hit run
Public Sub CountWorksheets()
MsgBox "Total Sheets count:" & Application.Sheets.Count
End Sub
You'll get a relevant output like below
We can now use: int Workbook.Sheets.Count
I use this code:
//Create application.
Microsoft.Office.Interop.Excel.Application ObjExcel = new Microsoft.Office.Interop.Excel.Application();
//Opening excel book
Workbook ObjWorkBook = ObjExcel.Workbooks.Open(excelFileLocation, 0, false, 5, "", "", false, XlPlatform.xlWindows, "", true, false, 0, true, false, false);
//Getting sheets count
int sheetsCount = ObjWorkBook.Worksheets.Count;
For this code to work, you need to install the package using NuGet - Microsoft.Office.Interop.Excel

Categories