Good day to all.
I am trying to merge all the sheets of multiple excel files into one excel file. I have successfully did it using below code:
string folder = textBox1.Text;
string[] xlsxfiles = Directory.GetFiles(folder, "*.xlsx");
Excel.Application app = new Excel.Application();
app.Visible = true;
Excel.Workbook finalWB = app.Workbooks.Add("");
Excel.Workbook tempWB = app.Workbooks.Add(xlsxfiles);
for (int i = 2; i <= app.Workbooks.Count; i++)
{
for (int j = 1; j <= app.Workbooks[i].Worksheets.Count; j++)
{
Excel.Worksheet ws = app.Workbooks[i].Worksheets[j];
ws.Copy(app.Workbooks[1].Worksheets[1]);
}
}
However, the workbooks "tempWB" are still open and some of them got their filenames "1" added at the end (e.g.Book1.xlsx becomes Book11.xlsx).
I've already tried:
tempWB.Close();
but it is not closing the ones with "1" added to their filenames.
Is there a code that I can use to close all open excel files except one (finalWB in my code)?
Thank you in advanced for the ususal help.
I think app.Workbooks.Close(); needs to be called at the end to close all the open workbooks is there are any.
I have successfully closed all excel sheets by Saving As first the active workbook then run
app.Workbook.Close()
my code looks like below
finalWB.SaveAs(excelReportSaveas, Microsoft.Office.Interop.Excel.XlFileFormat.xlWorkbookDefault, Type.Missing, Type.Missing,
false, false, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlNoChange,
Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
app.Workbooks.Close();
Thank you Gowri for the reply.
Related
I have a UWP app that I am developing in Visual Studio. It successfully makes api calls and returns data. So far I have only bound this data to grid views for displaying. Now however I would like to add a "save" function that will export this data to an excel document.
Any thoughts on how I could go about this ?
Any help is greatly appreciated.
I would advise you NOT to use excel directly, but use a different approach; try to get a nuget package to do the work for you (handling excel etc). Excel itself (as interop library) is a pain in the proverbial but cheeks.
A good one : https://www.nuget.org/packages/EPPlus/
You can still use the same data you get for your grid, but export it to excel. There are numerous examples to be found for above mentioned EPPLus.
try this
private void button_SAVE(object sender, EventArgs e)
{
// creating Excel Application
Microsoft.Office.Interop.Excel._Application app = new Microsoft.Office.Interop.Excel.Application();
// creating new WorkBook within Excel application
Microsoft.Office.Interop.Excel._Workbook workbook = app.Workbooks.Add(Type.Missing);
// creating new Excelsheet in workbook
Microsoft.Office.Interop.Excel._Worksheet worksheet = null;
// see the excel sheet behind the program
app.Visible = true;
// get the reference of first sheet. By default its name is Sheet1.
// store its reference to worksheet
worksheet = workbook.Sheets["Sheet1"];
worksheet = workbook.ActiveSheet;
// changing the name of active sheet
worksheet.Name = "Exported from gridview";
// storing header part in Excel
for (int i = 1; i < dataGridView1.Columns.Count + 1; i++)
{
worksheet.Cells[1, i] = dataGridView1.Columns[i - 1].HeaderText;
}
// storing Each row and column value to excel sheet
for (int i = 0; i < dataGridView1.Rows.Count - 1; i++) {
for (int j = 0; j < dataGridView1.Columns.Count; j++) {
worksheet.Cells[i + 2, j + 1] = dataGridView1.Rows[i].Cells[j].Value.ToString();
}
}
// save the application
workbook.SaveAs("c:\\output.xls", Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlExclusive, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
// Exit from the application
app.Quit();
See Sunteen's reply in this post. There are exist libraries which can do this.(Example doc)
If you want to create csv yourself, there is a blog about parsing CSV.
I like to delete rows from multiple worksheet in Excel. Currently my code only delete rows from active worksheet. I am looking for a specific value on the cell then when I find this value then I am deleting all the rows up to that value that stored on that row.
Code
private void button2_Click(object sender, EventArgs e)
{
Microsoft.Office.Interop.Excel.Application Excel = new Microsoft.Office.Interop.Excel.Application();
Workbook workBook = Excel.Workbooks.Open(FilePath);
Worksheet ws = (Worksheet)Excel.ActiveSheet;
for (int j = 1; j <= 10; j++)
{
for (int i = 1; i <= 20; i++)
{
if (Convert.ToString(((Microsoft.Office.Interop.Excel.Range)ws.Cells[j, i]).Value2) == "Matter")
{
for (int r = 1; r <= j; r++)
{
((Range)ws.Rows[r]).Delete(XlDeleteShiftDirection.xlShiftUp);
MessageBox.Show(Convert.ToString(r));
workBook.SaveAs(#"C:\Users\Separate\New.xlsx", Microsoft.Office.Interop.Excel.XlFileFormat.xlWorkbookDefault, Type.Missing, Type.Missing,
false, false, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlNoChange,
Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
}
}
}
}
workBook.Close(Type.Missing, Type.Missing, Type.Missing);
Excel.Quit();
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(Excel);
Excel = null;
}
I would highly suggest trying to use ClosedXML as it makes working with Excel so much easier. Specifically with ClosedXML you can have a line like this:
ws.Row(5).Delete();
where ws is your initialized worksheet, and it handles the heavy lifting for deleting that row.
Getting or setting cell data is just as simple:
ws.Cell(2, 2).Value = "Initial Value";
or alternatively
ws.Cell("B2").Value = "Value;
They also have type specific value assignment like this:
ws.Cell("B2").SetValue<T>(object);
The documentation is very thorough, and you can get the package through nuget (note it requires the DocumentFormat.OpenXML package installed as well)
EDIT:
I missed the part about multiple worksheets so here it is. The XLWorkbook type has a property Worksheets, which is an enumerable of all the worksheets in the workbook. Use this to get the worksheets you want to delete rows on
My program, every hour, does some math calculations and saves these result into excel. When it first run(lets say 08:00 AM) it creates a excel workbook and one sheet namely "Sheet1". It saves excel and releases the COM objects. so far everything is fine.
My problem begins with second run (09:00 AM). when it tries to save new results, it overwrites existing excel file (This is OK, the way i want it) but it overwrites Sheet1 which was created in 08:00 AM. I want it to save new result in Sheet2.
In third run, i want it to save result in Sheet3
In fourth run, i want it to save result in Sheet4. so on so forth..
How can i change my code to do like above ?
thanks in advance..
My Code:
using excelApp = Microsoft.Office.Interop.Excel;
public static void Main(string[] arg)
{
while (true)
{
writeToExcel();
int wait = 3600 * 1000;
System.Threading.Thread.Sleep(Convert.ToInt32(wait));
}
}
public static void writeToExcel()
{
excelApp.Application excl = new Microsoft.Office.Interop.Excel.Application();
excl.Visible = true;
//MATH CALCULATIONS......
excelApp.Workbook wb = excl.Workbooks.Add(excelApp.XlWBATemplate.xlWBATWorksheet);
excelApp.Worksheet ws1 = (excelApp.Worksheet)wb.Worksheets[1];
excelApp.Worksheet ws2 = (excelApp.Worksheet)wb.Sheets.Add();
excelApp.Worksheet ws3 = (excelApp.Worksheet)wb.Sheets.Add();
excelApp.Worksheet ws4 = (excelApp.Worksheet)wb.Sheets.Add();
excelApp.Worksheet ws5 = (excelApp.Worksheet)wb.Sheets.Add();
excl.DisplayAlerts = false;
string fileName = string.Format(#"{0}\Data_" + DateTime.Now.Month + "-" DateTime.Now.Day + ".xlsx", Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory));
workSheet.SaveAs(fileName);
Console.WriteLine("Excel Saved Successfully!!");
excl.Quit();
// Release COM objects
if (excl != null)
System.Runtime.InteropServices.Marshal.ReleaseComObject(excl);
if (workSheet != null)
System.Runtime.InteropServices.Marshal.ReleaseComObject(workSheet);
excl = null;
workSheet = null;
GC.Collect();
}
You need to get the work book from the saved file. So at the beginning of your routine, you need a mechanism to determine if today's file already exists, if so, use the the following to get your Workbook.
Workbook WB = ExcelApp.Workbooks.Open(fileName, 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);
Hopefully this helps you see the error in your ways.
I have created a set of code to export images from my Image folder into Excel using Microsoft Interop, now I want to change my codes from Microsoft Interop to EPPlus.
Can someone help me with this?
This is my codes:
Microsoft.Office.Interop.Excel._Application app = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel._Workbook workbook = app.Workbooks.Add(Type.Missing);
string[] filesindirectory = Directory.GetFiles(Server.MapPath("~/Image"));
int count = 0;
foreach (string img in filesindirectory)
{
count++;
Excel.Worksheet worksheet = (Excel.Worksheet)workbook.Worksheets.Add();
System.Web.UI.WebControls.Image TEST_IMAGE = new System.Web.UI.WebControls.Image();
worksheet.Name = "Title- " + count;
TEST_IMAGE.ImageUrl = "Image/" + Path.GetFileName(img);
TEST_IMAGE.ImageUrl = this.GetAbsoluteUrl(TEST_IMAGE.ImageUrl);
worksheet.Shapes.AddPicture(TEST_IMAGE.ImageUrl, Microsoft.Office.Core.MsoTriState.msoFalse, Microsoft.Office.Core.MsoTriState.msoCTrue, 50, 50, 300, 300);
}
workbook.Worksheets["Sheet1"].Delete();
workbook.Worksheets["Sheet2"].Delete();
workbook.Worksheets["Sheet3"].Delete();
workbook.SaveAs(#"C:\Users\user\Desktop\Test\" + datetime.ToString("dd-MM-yyyy_hh-mm-ss") + ".xlsx", Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlExclusive, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
app.Quit();
Thanks.
To read an image into excel via epplus you can use this as an example (it will also show you how to setup a new workbook from scratch):
Weird behavior when setting a row's height on EPPlus
To delete a worksheet you can do that like this:
using (var pack = new ExcelPackage(existingFile))
{
var ws = pack.Workbook.Worksheets.Add("sheet1");
pack.Workbook.Worksheets.Delete(ws);
...
}
But if you are just trying to clean out the default sheets created by excel when you create a new file you DONT need to do that with EPPlus - by default there are no sheet when creating a new package (i.e. workbook). It is up to the programmer to add sheets and it will throw an error if there is not at least one.
I create an Excel file from c# with data validation-it seem like combo with chosen possibility
string mList1 = "=ProductCode";
oRng = oSheet.get_Range("H8", "H9");
oRng.Name = "ProductCode";
int t = dt.Rows.Count + 2;
string st = "F" + t;
oRng = oSheet.get_Range("F2", st);
oRng.Validation.Add(XlDVType.xlValidateList,
XlDVAlertStyle.xlValidAlertStop,
Missing.Value, mList1, Missing.Value);
Now I want to read the Excel file and also the chosen item from the combo. I have successfully read all the data but the data validation.
Read the data-
Microsoft.Office.Interop.Excel.Application ExcelObj = null;
ExcelObj = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel.Workbook theWorkbook = ExcelObj.Workbooks.Open("C:\\Documents and Settings\\rachelg\\My Documents\\xxx.xls"
,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);
Microsoft.Office.Interop.Excel.Sheets sheets = theWorkbook.Worksheets;
Microsoft.Office.Interop.Excel.Worksheet worksheet = (Microsoft.Office.Interop.Excel.Worksheet)sheets.get_Item(1);
for(int x = 1; x <= 5; x++)
{
string sd = ((Microsoft.Office.Interop.Excel.Range)worksheet.Cells[x, 1]).Text.ToString();
System.Console.WriteLine(sd);//this one column
}
in different column I have the data validation but I don't know to access into it.
That seems a bit much for what is largely a simple operation.
Whilst not answering your question directly, this post I made a while back might help: accessing data record from Excel in VB.NET.