C#: Writing file to Excel issue - c#

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.

Related

How can I export data to an Excel file with APP WinUI3?

I don't know how to export data from a ListView to Excel using a Winui3 APP tecnology.
With WPF I used "Excel = Microsoft.Office.Interop.Excel"
but in WinUI3 technology it doesn't work
Excel._Workbook MyExBook;
Excel.Workbooks MyExBooks;
Excel._Worksheet MyExSheet;
Excel.Sheets MyExSheets;
Excel.Range MyExRange;
ButExcel.IsEnabled = false;
try
{
MyExApp = new Excel.Application();
MyExBooks = MyExApp.Workbooks;
MyExBook = MyExBooks.Add();
MyExSheets = MyExBook.Worksheets;
MyExSheet = (Excel.Worksheet)MyExSheets[1];
}
catch
{
ButExcel.IsEnabled = true;
return;
}
There's no reason to use Excel itself to generate xlsx files. These files are ZIP packages containing well-defined XML files. There several libraries that can easily generate real Excel files, eg Epplus, ClosedXML, NPOI and many more.
These libraries offer several convenience methods that can load data from collections, DataTables or DataReaders directly. For example, using EPPlus, you can create an Excel file from a list of Products with :
var producs=new List<Product>();
//Load the list somehow
using (var p = new ExcelPackage())
{
var sheet = pck.Workbook.Worksheets.Add("sheet");
var range = sheet.Cells["C1"].LoadFromCollection(products);
p.SaveAs(new FileInfo(#"c:\workbooks\myworkbook.xlsx"));
}
You can load the data with headers, as a table, using one of the predefined styles too:
var tableRange = sheet.Cells["C1"].LoadFromCollection(products, true, TableStyles.Dark1);
// to get access to the created table:
var table = sheet.Tables.GetFromRange(tableRange);
ClosedXML allows writing similar code :
var wb = new XLWorkbook();
var ws = wb.Worksheets.Add("Inserting Data");
var rangeWithPeople = ws.Cell(7, 6).InsertData(people.AsEnumerable());
...
wb.SaveAs("InsertingData.xlsx");
To create a table you need to use InsertTable instead of InsertData:
var table= ws.Cell(7, 6).InsertTable(people.AsEnumerable(),"MyTable");
Both libraries also work with DataTable results

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)?

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";

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;

Convert xls or xlsx file with multiple sheets into one csv file using interop

I am trying to convert a xls or xlsx file with multiple sheets into one CSV file using c# and the interop library. I am only getting the one sheet in the CSV file. I know I can specify the sheet to save as or change the active sheet to save that one but I am looking for a solution to append all the sheets to the same CSV file that will work with both xls and xlsx files. I am automating this and don't care what is in the excel document just want to pull the string values out and append it to the csv file. Here is the code I am using:
Microsoft.Office.Interop.Excel.Application app = new Microsoft.Office.Interop.Excel.Application();
app.Visible = false;
app.DisplayAlerts = false;
Workbook wkb = app.Workbooks.Open(fullFilePath);
wkb.SaveAs(newFileName, XlFileFormat.xlCSVWindows);
Is this even possible?
I'm just getting started tackling a similar situation, but I believe this may address your needs:
http://www.codeproject.com/Articles/246772/Convert-xlsx-xls-to-csv
This uses the ExcelDataReader api that you can get from NuGet
http://exceldatareader.codeplex.com/
Like Tim was saying, you're going to have to make sure and possibly validate that the columns and structure are the same between sheets. You may also have to eat the header rows on all the sheets after the first one. I'll post an update and some code samples once I've finished.
Update [7/15/2013]. Here's my finished code. Not very fancy, but it gets the job done. All of the sheets are tables in the DataSet, so you just loop through the tables adding onto your destination. I'm outputting to a MongoDB, but I'm guessing you can swap that out for a StreamWriter for your CSV file rather easily.
private static void ImportValueSetAttributeFile(string filePath)
{
FileStream stream = File.Open(filePath, FileMode.Open, FileAccess.Read);
// Reading from a OpenXml Excel file (2007 format; *.xlsx)
IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
// DataSet - The result of each spreadsheet will be created in the result.Tables
DataSet result = excelReader.AsDataSet();
// Free resources (IExcelDataReader is IDisposable)
excelReader.Close();
var connectionString = ConfigurationManager.ConnectionStrings[0].ConnectionString;
var database = ConfigurationManager.AppSettings["database"];
var mongoAccess = new MongoDataAccess(connectionString, database);
var cdm = new BaseDataManager();
int ind = 0;
for (int i = 0; i < result.Tables.Count; i++)
{
int row_no = 1;
while (row_no < result.Tables[ind].Rows.Count) // ind is the index of table
// (sheet name) which you want to convert to csv
{
var currRow = result.Tables[ind].Rows[row_no];
var valueSetAttribute = new ValueSetAttribute()
{
CmsId = currRow[0].ToString(),
NqfNumber = currRow[1].ToString(),
ValueSetName = currRow[2].ToString(),
ValueSetOid = currRow[3].ToString(),
Definition = currRow[4].ToString(),
QdmCategory = currRow[5].ToString(),
Expansion = currRow[6].ToString(),
Code = currRow[7].ToString(),
Description = currRow[8].ToString(),
CodeSystem = currRow[9].ToString(),
CodeSystemOid = currRow[10].ToString(),
CodeSystemVersion = currRow[11].ToString()
};
cdm.AddRecords<ValueSetAttribute>(valueSetAttribute, "ValueSetAttributes");
row_no++;
}
ind++;
}
}

Categories