How to copy pre-generated csv file into xlsx with c# - c#

I'm writing a program that copy specific columns from pre-generated .csv file to template xlsx file. With my code I'am only able to achive copying the whole csv file to the first column. Any tips how to make the program see " ; " as a separator during pasting?
Also if I overpass this problem how to copy only specific columns that i choose?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Excel = Microsoft.Office.Interop.Excel;
namespace Kreator
{
class Program
{
static void Main(string[] args)
{
Excel.Application srcApp;
Excel.Workbook srcWorkbook;
Excel.Worksheet srcWorksheet;
Excel.Application destApp;
Excel.Workbook destWorkbook;
Excel.Worksheet destWorksheet;
string srcPath = "C:\\Users\\Desktop\\Raport.csv";
string destPath = "C:\\Users\\Desktop\\XXX.xlsx";
srcApp = new Excel.Application();
srcWorkbook = srcApp.Workbooks.Open(srcPath);
srcWorksheet = srcWorkbook.Worksheets.get_Item(1);
destApp = new Excel.Application();
destWorkbook = destApp.Workbooks.Open(destPath,0,false);
destWorksheet = destWorkbook.Worksheets.get_Item(1);
Excel.Range srcRange = srcWorksheet.get_Range("A1", "C20");
Excel.Range destRange = destWorksheet.get_Range("C10","E29");
srcRange.Copy(Type.Missing);
destRange.PasteSpecial(Microsoft.Office.Interop.Excel.XlPasteType.xlPasteValu es, Microsoft.Office.Interop.Excel.XlPasteSpecialOperation.xlPasteSpecialOperationNone);
destWorkbook.SaveAs("C:\\Users\\Desktop\\GotowyPlik" + DateTime.Now.ToString("MM_dd_yyyy") + ".xlsx");
srcApp.Application.DisplayAlerts = false;
destApp.Application.DisplayAlerts = false;
srcWorkbook.Close(false, null, null);
destWorkbook.Close(true, null, null);
destApp.Quit();
srcApp.Quit();
}
}
}

Related

I try to open an Excel file with C#, I get this error: System.Runtime.InteropServices.COMException HResult=0x800A03E

I try to open an Excel file in C#, but I get this error:
System.Runtime.InteropServices.COMException HResult=0x800A03E
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Threading;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using excel = Microsoft.Office.Interop.Excel;
namespace Example_Reading_A_File_From_Excel
{
class Program
{
static void Main(string[] args)
{
excel.Application x1app = new excel.Application();
excel.Workbook x1workbook = x1app.Workbooks.Open(#"‪D:\saniaertest.xlsx");
excel._Worksheet x1worksheet = x1workbook.Sheets[1];
excel.Range x1range = x1worksheet.UsedRange;
string website;
for(int i = 1; i <= 3; i++)
{
website = x1range.Cells[i][9].value2;
IWebDriver driver = new ChromeDriver();
driver.Navigate().GoToUrl(website);
Thread.Sleep(30);
driver.Close();
}
}
}
}
Normally it should open the Excel file and open the Chrome browser and navigate to all the URL that are listed in column 9. But like said before I only get the error:
System.Runtime.InteropServices.COMException HResult=0x800A03E
It says that the workbook can't be found.
That's very odd because I tried the first few lines of your code and I was getting the same error although my file did exist where I placed it.
For some reason, the Workbooks.Open is not pointing to the correct file path so
I had to update it to the following:
string file = Directory.GetCurrentDirectory() + "\\" + "Test.xlsx";
if (File.Exists(file))
{
excel.Application x1app = new excel.Application();
excel.Workbook x1workbook = x1app.Workbooks.Open(file);
excel._Worksheet x1worksheet = x1workbook.Sheets[1];
excel.Range x1range = x1worksheet.UsedRange;
}
This worked for me as I no longer get the error that the workbook cannot be found.
I suggest using the ExcelDataReader package instead. It does not require having Excel or the InteropServices installed on a machine. As a bonus it also works to read files while running in Linux.
using (var stream = File.Open(filePath, FileMode.Open, FileAccess.Read))
{
// Auto-detect format, supports:
// - Binary Excel files (2.0-2003 format; *.xls)
// - OpenXml Excel files (2007 format; *.xlsx)
using (var reader = ExcelReaderFactory.CreateReader(stream))
{
// Choose one of either 1 or 2:
// 1. Use the reader methods
do
{
while (reader.Read())
{
// reader.GetDouble(0);
}
} while (reader.NextResult());
// 2. Use the AsDataSet extension method
var result = reader.AsDataSet();
// The result of each spreadsheet is in result.Tables
}
}
-Example from:
https://github.com/ExcelDataReader/ExcelDataReader

Program that reads from 2 excel files and enables users to search relevant fields from both files

This is supposed to be a program that reads from 2 excel files, stores the data in two arrays and enables users to search via textbox for a specific zip/place and upon the input in the search box to be prompted with the place/s that relate/s to it via lable or vice versa.
My problem is that it takes too much time for the files to be red. I am open for suggestions how to shorten the read time.
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Excel = Microsoft.Office.Interop.Excel ;
namespace ExcelDateilesen_1
{
public partial class Form1 : Form
{
string[] zip = new string[3000];
string[] place = new string[3000];
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Excel.Application objExcel = new Excel.Application();
Excel.Workbook objWorkbook = objExcel.Workbooks.Open
(#"C:\Users\ggr\Documents\plz.xlsx");
Excel.Worksheet objWorksheet = objWorkbook.Worksheets["Tabelle1"];
Excel.Range objCell;
int i = 1;
do
{
objCell = objWorksheet.Cells[i, 1];
if (objCell.Value == null) break;
if (objCell.Value is string)
{
zip[i - 1] = objCell.Value;
}
i++;
} while (true);
objWorkbook.Close();
objExcel.Quit();
Excel.Application objExcel1 = new Excel.Application();
Excel.Workbook objWorkbook1 = objExcel1.Workbooks.Open
(#"C:\Users\ggr\Documents\ort.xlsx");
Excel.Worksheet objWorksheet1 = objWorkbook1.Worksheets["Tabelle1"];
Excel.Range objCell1;
int j = 1;
do
{
objCell1 = objWorksheet1.Cells[j, 1];
if (objCell1.Value == null) break;
if (objCell1.Value is string)
{
place[j - 1] = objCell1.Value;
}
j++;
} while (true);
objWorkbook1.Close();
objExcel1.Quit();
}
}
}
It took about 20 seconds to read each Excel file containing 3000 rows of data using your code. Instead of looping through the Excel file and looking for a null cell, I created a method (ReadSheet) that would take an Excel worksheet and return a string array of the first column of data for 3000 rows. I used an object Array to get all the cell values, and then cast it to a string array. Reading was much faster. Unfortunately I was unable to take advantage of the worksheet.UsedRange function to get all the rows no matter how many, because it kept giving me the wrong number. I will have to look into this. Hope this helps.
EDIT: Changed to UsedRange to get all cells. The problem I had was with the excel sheet I was using.
public partial class Form1 : Form
{
string[] zip;
string[] place;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Excel.Application objExcel = new Excel.Application();
Excel.Workbook objWorkbook = objExcel.Workbooks.Open(#"C:\Users\John\Desktop\cs\TestExcel2_3000.xlsx");
Excel.Worksheet objWorksheet = objWorkbook.Worksheets["Tabelle1"];
zip = ReadSheet(objWorksheet);
objWorkbook.Close();
Excel.Workbook objWorkbook1 = objExcel.Workbooks.Open(#"C:\Users\John\Desktop\cs\TestExcel3_3000.xlsx");
Excel.Worksheet objWorksheet1 = objWorkbook1.Worksheets["Tabelle1"];
place = ReadSheet(objWorksheet1);
objWorkbook1.Close();
objExcel.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(objWorkbook);
System.Runtime.InteropServices.Marshal.ReleaseComObject(objWorkbook1);
System.Runtime.InteropServices.Marshal.ReleaseComObject(objExcel);
}
private string[] ReadSheet(Excel.Worksheet inSheet)
{
Excel.Range targetCells = inSheet.UsedRange;
//Excel.Range targetCells = inSheet.Range["A1:A3000"];
Array allValues = (Array)targetCells.Cells.Value;
return allValues.Cast<string>().ToArray();
}
}

Merge multiple workbooks in one (new) master workbook using C#

I need some help on integrating multiple workbooks into a single master workbook. I am trying to use the following code. I would really appreciate if someone could please help me with following problems:
saving the final (master) workbook having all the worksheets
the worksheets in different workbooks should not loose formatting while copying to master workbook.
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Excel = Microsoft.Office.Interop.Excel;
using Microsoft.Office.Interop.Excel;
using System.IO;
namespace IntegrationMacro
{
class Program
{
static void Main(string[] args)
{
Excel.Application app = new Excel.Application();
app.Visible = true;
app.Workbooks.Add("");
app.Workbooks.Add(#"C:\Users\ssehgal\Documents\Excel-Files-For-Macro\WorkBook1.xls");
app.Workbooks.Add(#"C:\Users\ssehgal\Documents\Excel-Files-For-Macro\WorkBook2.xls");
for (int i = 2; i <= app.Workbooks.Count; i++)
{
for (int j = 1; j <= app.Workbooks[i].Worksheets.Count; j++)
{
Excel.Worksheet ws = (Excel.Worksheet)app.Workbooks[i].Worksheets[j];
ws.Copy(app.Workbooks[1].Worksheets[1]);
}
}
}
}
}
var app = new Application() { Visible = true };
var master = app.Workbooks.Add();
// repeat this for each workbook you need to combine...
app.Workbooks.Add(__PATH_TO_THE_WORKBOOK__)
.Worksheets.Cast<Worksheet>()
.ToList() // Move() will modify the source of enumeration, so we need to make a temp copy
.ForEach(x => x.Move(master.Sheets[1]));

Reading an Excel file UsedRange error

I basically need my code to read one by one all cells in an excel file and then upload then to a database.
I've read on several answers to this question I should use the UsedRange but everytime I do I get an error saying there is no definition for UsedRange.
I added a reference to the excel interop but no dice.
Any advice would be appreciated.
And I know the code looks terrible now but I just wanted to test if I could read data from an excel file.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Excel = Microsoft.Office.Interop.Excel;
namespace ConsoleApplication28
{
class Program
{
static void Main()
{
Excel.Application excelApp = new Excel.Application();
excelApp.Visible = true;
string workbookPath = "C:/Users/Sidney/Desktop/CrystalViewer-11.xls";
Excel.Workbook excelWorkbook = excelApp.Workbooks.Open(workbookPath,
0, false, 5, "", "", false, Excel.XlPlatform.xlWindows, "",
true, false, 0, true, false, false);
Excel.Sheets excelSheets = excelWorkbook.Worksheets;
string currentSheet = "Sheet1";
Excel.Worksheet excelWorksheet = (Excel.Worksheet)excelSheets.get_Item(currentSheet);
Excel.Range range;
range = excelSheets.UsedRange;
int rows_count = range.Rows.Count;
string output = null;
}
}
}
You're trying to access UsedRange on the wrong Object. UsedRange is a property of Worksheet, so your code should be:
range = excelWorksheet.UsedRange;
Excel.Range xlRange = excelWorkbook.ActiveSheet.UsedRange;

copying of specific range of excel cells from one worksheet to another worksheet

I am writing a C# program which copies a range of cells from a worksheet of one workbook to a worksheet of an other workbook. But the problem I am facing is I am only able to copy and paste the whole worksheet of first workbook. I want to know how to select only a specific range(from row 5 [column 1 to column 10] to row 100 [column 1 to column 10]) and paste it in second workbook worksheet starting from row 2 column 8.
Also i want to know how a fill a column say from C1 to C100 with some value in a direct way instead of using the loop like below
for(i=1;i<2;i++)
{
for(j=1;j<101;i++)
{
worksheet.cells[i,j]="Fixed";
}
}
Here is the code that i have written so far
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Excel = Microsoft.Office.Interop.Excel;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
Excel.Application srcxlApp;
Excel.Workbook srcworkBook;
Excel.Worksheet srcworkSheet;
Excel.Range srcrange;
Excel.Application destxlApp;
Excel.Workbook destworkBook;
Excel.Worksheet destworkSheet;
Excel.Range destrange;
string srcPath;
string destPath;
//Opening of first worksheet and copying
srcPath="C:\\Documents and Settings\\HARRY\\Desktop\\incident.csv";
srcxlApp = new Excel.Application();
srcworkBook = srcxlApp.Workbooks.Open(srcPath);
srcworkSheet = srcworkBook.Worksheets.get_Item(1);
srcrange = srcworkSheet.UsedRange;
srcrange.Copy(Type.Missing);
//opening of the second worksheet and pasting
destPath = "C:\\Documents and Settings\\HARRY\\Desktop\\FIXED Aging incident Report.xls";
destxlApp = new Excel.Application();
destworkBook = destxlApp.Workbooks.Open(destPath,0,false);
destworkSheet = destworkBook.Worksheets.get_Item(1);
destrange = destworkSheet.Cells[1, 1];
destrange.Select();
destworkSheet.Paste(Type.Missing, Type.Missing);
destworkBook.SaveAs("C:\\Documents and Settings\\HARRY\\Desktop\\FIXED Aging incident Report " + DateTime.Now.ToString("MM_dd_yyyy") + ".xls");
srcxlApp.Application.DisplayAlerts = false;
destxlApp.Application.DisplayAlerts = false;
destworkBook.Close(true, null, null);
destxlApp.Quit();
srcworkBook.Close(false, null, null);
srcxlApp.Quit();
}
}
}
You should be able to do this:
Excel.Range from = srcworkSheet.Range("C1:C100");
Excel.Range to = destworkSheet.Range("C1:C100");
from.Copy(to);
mrtig has a very elegant solution. But it won't work if you have the workbooks in separate instances of excel. So, the key is to open them in just one instance. I've modified your example to show using this approach:
public void CopyRanges()
{
// only one instance of excel
Excel.Application excelApplication = new Excel.Application();
srcPath="C:\\Documents and Settings\\HARRY\\Desktop\\incident.csv";
Excel.Workbook srcworkBook = excelApplication.Workbooks.Open(srcPath);
Excel.Worksheet srcworkSheet = srcworkBook.Worksheets.get_Item(1);
destPath = "C:\\Documents and Settings\\HARRY\\Desktop\\FIXED Aging incident Report.xls";
Excel.Workbook destworkBook = excelApplication.Workbooks.Open(destPath,0,false);
Excel.Worksheet destworkSheet = destworkBook.Worksheets.get_Item(1);
Excel.Range from = srcworkSheet.Range("C1:C100");
Excel.Range to = destworkSheet.Range("C1:C100");
// if you use 2 instances of excel, this will not work
from.Copy(to);
destworkBook.SaveAs("C:\\Documents and Settings\\HARRY\\Desktop\\FIXED Aging incident Report " + DateTime.Now.ToString("MM_dd_yyyy") + ".xls");
srcxlApp.Application.DisplayAlerts = false;
destxlApp.Application.DisplayAlerts = false;
destworkBook.Close(true, null, null);
srcworkBook.Close(false, null, null);
excelApplication.Quit();
}
For the First part of setting the same value for the entire range, instead of looping following will work out
range1 = workSheet.get_Range("A1:B100");
range1.Value = "Fixed";
And for copying you can try what #mrtig has suggested.

Categories