C# Excel: Issue in copying worksheet from different workbook - c#

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.

Related

C# cannot read from read-only Excel file

I have a folder on my PC containing multiple Excel spreadsheets that are all marked as read-only.
The folder is synced to my company's Sharepoint via OneDrive.
When I try to programmatically read data from one of these sheets via Microsoft.Office.Interop.Excel, I keep getting the You cannot use this command on a protected sheet error.
Here's the code I use to open the file:
public ExcelReader(String filePath)
{
this.filePath = filePath;
FileName = filePath.Substring(filePath.LastIndexOf("\\")+1);
app = new Excel.Application();
app.DisplayAlerts = false;
workbook = app.Workbooks.Open(filePath, false, true); //open in read only
}
public void openSheet(String sheet)
{
SheetName = sheet;
worksheet = workbook.Sheets[sheet];
Excel.Range last = worksheet.Cells.SpecialCells(Excel.XlCellType.xlCellTypeLastCell, Type.Missing);
ColumnsTotal = last.Column;
RowsTotal = last.Row;
}
The line that throws the exception is Excel.Range last = worksheet.Cells.SpecialCells(Excel.XlCellType.xlCellTypeLastCell, Type.Missing);.
I figured that since I explicitly tell the Workbook to open in Read-only mode, and since I never modify the content of these files, the fact that files are read-only shouldn't be a problem.
What am I doing wrong here? How do I read the content of these files without unprotecting them (I can't do that for security reasons)?

Returning Excel variables 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;

How to set active sheet with Open XML SDK 2.5

using the example here How to Copy a Worksheet within a Workbook
I have successfully been able to clone/copy sheets in my excel file, however when I open the excel the 2nd sheet is the active(visible) sheet. I haven't been able to locate a property that could do thins.....Is there any way to specify what sheet is active?
I've tried to force it by opening and editing the first sheet in the file thinking it was the last edited sheet that was active but that didn't work either.
any help would be great. TIA
update: looking at the workbook.xml created when renaming the .xlsx to .zip I came accross the 'activeTab' property. made a quick change to my code and seems to work just fine
public void SetFirstSheetInFocus(String xlsxFile)
{
using (SpreadsheetDocument spreadSheet = SpreadsheetDocument.Open(xlsxFile, true))
{
//Get a reference to access the main Workbook part, which contains all references
WorkbookPart _workbookPart = spreadSheet.WorkbookPart;
if (_workbookPart != null)
{
WorkbookView _workbookView = spreadSheet.WorkbookPart.Workbook.BookViews.ChildElements.First<WorkbookView>();
if (_workbookView != null)
{
_workbookView.ActiveTab = 0; // 0 for first or whatever tab you want to use
}
// Save the workbook.
_workbookPart.Workbook.Save();
}
}
}
If the name of your sheet is in the variable
sheetName
you can set the sheet with that name active like this:
using (var spreadsheetDoc = SpreadsheetDocument.Open(emptyHIPTemplatePath, true /* isEditable */, new OpenSettings { AutoSave = false }))
{
var workbookPart = spreadsheetDoc.WorkbookPart;
var workBook = spreadsheetDoc.WorkbookPart.Workbook;
var sheet = workBook.Descendants<Sheet>().FirstOrDefault(s => s.Name == sheetName);
var sheetIndex = workBook.Descendants<Sheet>().ToList().IndexOf(sheet);
var workBookView = workBook.Descendants<WorkbookView>().First();
workBookView.ActiveTab = Convert.ToUInt32(sheetIndex);
...
workBook.Save();
}
From Vincent Tan's book:
The SheetId property doesn't determine the order. The order of
appending the Sheet classes to the Sheets class, does.
When you add a sheet, it gets the next index, but a single sheet does not have an index. OpenXML gives it an index when you are done adding sheets. Again, from Vincent Tan's book:
Let's say you have 3 worksheets named Sheet1, Sheet2 and Sheet3.
However, when you appended the corresponding Sheet classes, you did it
as Sheet2, Sheet3 and Sheet1, in that order.

excel cell coloring

I am using c# to color particular cells of excel file.
i am using
Application excel = new Application();
Workbook wb = excel.Workbooks.Open(destPath);
Worksheet ws = wb.Worksheets[1];
ws.Cells[row, clmn].Interior.Color = XlRgbColor.rgbBlack;
to color cells..But this is not working..
It is giving an exception on the last line where i am coloring the cells
"Exception from HRESULT: 0x800A03EC"
I am unable to fix the exception
Can anyone help me out..
It might not work because the worksheet is protected.
You can check it the following way:
Application excel = new Application();
Workbook wb = excel.Workbooks.Open(destPath);
Worksheet ws = wb.Worksheets[1];
bool wasProtected = ws.ProtectContents;
if (wasProtected == true)
{
// unprotect the worksheet
}
else
{
ws.Cells[row, clmn].Interior.Color = XlRgbColor.rgbBlack;
}
...
if (wasProtected == true)
{
// protect back the worksheet
}
In my previous project I used the following snippet to Color Cells in Excel:
ws.Cells[row, clmn].Interior.Color = System.Drawing.ColorTranslator.ToWin32(Color.Black);
I tested the code that you have on a new Excel file and it works fine. However, I was able to reproduce the error when testing with a row value of 0. So maybe the problem is with the row and clmn values. Otherwise it must be something specific to your Excel file... maybe a protected cell or something along those lines.

Export data from dataset to excel

I am trying to export data from dataset to excel and save it directly to a given path without giving me the option to open,save or cancel.
Using ExcelLibrary this is a one liner ...
DataSet myDataSet;
... populate data set ...
ExcelLibrary.DataSetHelper.CreateWorkbook("MyExcelFile.xls", myDataSet);
See also Create Excel (.XLS and .XLSX) file from C#
This C# Excel library can also be used to export the dataset. More details about how to export can be found here.
ExcelDocument xls = new ExcelDocument();
xls.easy_WriteXLSFile_FromDataSet("ExcelFile.xls", dataset,
new ExcelAutoFormat(Styles.AUTOFORMAT_EASYXLS1), "Sheet Name");
It's not the greatest solution but here is what I did, it opens a new excel document then copies what is in the dataset, all you need to do is sort out the columns and save it.
Btw totes my first post to answer a question, hope it helps
private void cmdExport_Click(object sender, EventArgs e)
{
System.Diagnostics.Process.Start("excel.exe");
try
{
copyAlltoClipboard();
Microsoft.Office.Interop.Excel.Application xlexcel;
Microsoft.Office.Interop.Excel.Workbook xlWorkBook;
Microsoft.Office.Interop.Excel.Worksheet xlWorkSheet;
object misValue = System.Reflection.Missing.Value;
xlexcel = new Excel.Application();
xlexcel.Visible = true;
xlWorkBook = xlexcel.Workbooks.Add(misValue);
xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
Excel.Range CR = (Excel.Range)xlWorkSheet.Cells[1, 1];
CR.Select();
xlWorkSheet.PasteSpecial(CR, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, true);
}
catch (Exception ex)
{
MessageBox.Show("Error :" + ex.Message);
}
}
private void copyAlltoClipboard()
{
dataGridViewItems.SelectAll();
DataObject dataObj = dataGridViewItems.GetClipboardContent();
if (dataObj != null)
Clipboard.SetDataObject(dataObj);
}
Check this DataSetToExcel
and c# (WinForms-App) export DataSet to Excel
In the first link change the code as follows:
Remove the all code that initially starts and try the following
using (StringWriter sw = new StringWriter("Your Path to save"))
{
using (HtmlTextWriter htw = new HtmlTextWriter(sw))
{
// instantiate a datagrid
DataGrid dg = new DataGrid();
dg.DataSource = ds.Tables[0];
dg.DataBind();
dg.RenderControl(htw);
}
}
Here's another C# library, which lets you export from a DataSet to an Excel 2007 .xlsx file, using the OpenXML libraries.
http://www.mikesknowledgebase.com/pages/CSharp/ExportToExcel.htm
All of the source code is provided, free of charge, along with a demo application, and you can use this in your ASP.Net, WPF and WinForms applications.
Once you've added the class to your application, it just takes one function call to export your data into an Excel file.
CreateExcelFile.CreateExcelDocument(myDataSet, "C:\\Sample.xlsx");
It doesn't get much easier than that.
Good luck !
Hi i found a perfect solution Here
Just replace 'missing.value' with System.Type.Missing in the code. Also remove
oWB.Close(System.Type.Missing, System.Type.Missing, System.Type.Missing);
and
oXL.Quit();
from the code. Otherwise your excel will get closed automatically as soon as it open.

Categories