I have an excel sheet containing single column and multiple rows like:
000500114673HY340216-00 CT TAPING WORK DTYPE-OSKF 245 TWB.T H/C 37990110000250000100
I am trying to create a new Excel file through my C# code, but not getting the desired result. In my new Excel file I need six columns with each column assigned a particular range, say for first column 12, for second 20 and so on (spaces also included). I used the text to column method, but I'm not able to parse it to fixed width. My code sample is:
xlAppNew = new Application();
xlAppNew.DisplayAlerts = true;
workbooks = xlAppNew.Workbooks;
workbook = workbooks.Open(#filepath, 0, true, 1, "", "", true,
Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t",
false, false, 0, true, 1, 0);
xlWorkSheet = (Microsoft.Office.Interop.Excel.Worksheet)workbook.Worksheets.get_Item(1);
((Range)xlAppNew.Cells[1, 1]).EntireColumn.TextToColumns(Type.Missing,
Microsoft.Office.Interop.Excel.XlTextParsingType.xlFixedWidth,
Microsoft.Office.Interop.Excel.XlTextQualifier.xlTextQualifierNone,
Type.Missing, Type.Missing, Type.Missing, true, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing);
I think the problem lies with the fourth last parameter, the fieldinfo object which I am not able to provide properly, I also used the array object, but it produced error. I took help from this question 4945621. But the exact solution is not provided there.
Actually what I had to do was first convert a DAT file to Excel and then divide it into fixed number of columns through my C# code. So in my first step what I did was converted the DAT file into an Excel file having a single column and given number of rows as my temporary Excel file.
xlAppNew1 = new Application();
xlAppNew1.DisplayAlerts = true;
workbooks1 = xlAppNew1.Workbooks;
workbook1 = workbooks1.Open(#filepath, 0, true, 1, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);
xlAppNew1.ActiveWorkbook.SaveAs(#filepathNew, -4143, "", "", false, false, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlNoChange,
missing, missing, missing, missing, missing);
Now make sure to close all the instances of the COM object that you have created otherwise it will create hell lot of a problem.Secondly in another function I opened my temporary Excel file, and all the data in a Dataset and then with the help of Range object and the following method:
range = range.get_Resize(range.Rows.Count, 9);
string[,] saRet = new string[range.Rows.Count, 9];
range.set_Value(Missing.Value, saRet);
The whole code goes something loke this:
xlAppNew = new Application();
xlAppNew.DisplayAlerts = true;
workbooks = xlAppNew.Workbooks;
workbook = workbooks.Open(#filepathnew, 0, true, 1, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);
xlWorkSheet = (Microsoft.Office.Interop.Excel.Worksheet)workbook.Worksheets.get_Item(1);
if (getExtension.ToLower() == ".xls")
connString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + filepath_second + ";Extended Properties=\"Excel 8.0;HDR=YES;IMEX=1;\"";
else
connString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + filepath_second + ";Extended Properties=Excel 12.0 Xml;HDR=Yes;IMEX=1;";
OleDbConnection con = new OleDbConnection(connString);
con.Open();
System.Data.DataTable dtSheet = con.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
string tname = dtSheet.Rows[0]["TABLE_NAME"].ToString();
OleDbDataAdapter ad = new OleDbDataAdapter(#"Select * FROM [" + tname + "];", con);
DataSet dset = new DataSet();
ad.Fill(dset);
range = xlWorkSheet.UsedRange;
range = range.get_Resize(range.Rows.Count, 9);
//Create an array.
string[,] saRet = new string[range.Rows.Count, 9];
//Fill the array.
for (int iRow = 0; iRow < range.Rows.Count - 1; iRow++)
{
for (int iCol = 0; iCol < 9; iCol++)
{
switch (iCol)
{
case 0:
saRet[iRow, iCol] = dset.Tables[0].Rows[iRow][0].ToString().Substring(3, 9);//iRow.ToString() + "|" + iCol.ToString();
break;
case 1:
saRet[iRow, iCol] = dset.Tables[0].Rows[iRow][0].ToString().Substring(12, 4);
break;
case 2:
saRet[iRow, iCol] = dset.Tables[0].Rows[iRow][0].ToString().Substring(16, 18);
break;
case 3:
saRet[iRow, iCol] = dset.Tables[0].Rows[iRow][0].ToString().Substring(34, 8);
break;
case 4:
saRet[iRow, iCol] = dset.Tables[0].Rows[iRow][0].ToString().Substring(42, 4);
break;
case 5:
saRet[iRow, iCol] = dset.Tables[0].Rows[iRow][0].ToString().Substring(46, 18);
break;
case 6:
saRet[iRow, iCol] = dset.Tables[0].Rows[iRow][0].ToString().Substring(64, 40);
break;
case 7:
saRet[iRow, iCol] = dset.Tables[0].Rows[iRow][0].ToString().Substring(104, 3);
break;
case 8:
saRet[iRow, iCol] = dset.Tables[0].Rows[iRow][0].ToString().Substring(107, 5);
break;
}
}
}
//Set the range value to the array.
range.set_Value(Missing.Value, saRet);
FieldInfo myf = typeof(MyNewService).GetField("saRet");//Fieldinfo object is also an important part
//**********************
((Range)xlAppNew.Cells[1, 1]).EntireColumn.TextToColumns(Type.Missing, Microsoft.Office.Interop.Excel.XlTextParsingType.xlFixedWidth, Microsoft.Office.Interop.Excel.XlTextQualifier.xlTextQualifierNone, Type.Missing, Type.Missing, Type.Missing, true, Type.Missing, Type.Missing, Type.Missing, myf, Type.Missing, Type.Missing, Type.Missing);
xlAppNew.ActiveWorkbook.SaveAs(#temp_path, -4143, "", "", false, false, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlNoChange, missing, missing, missing, missing, missing);
Hope it helps others to save their time.Thank You.
Related
I am trying to overwrite/edit a column in a sheet in my excel file, even though it is not throwing any error, but still it is not even updating the excel sheet.
Here is my code:
Cursor.Current = Cursors.WaitCursor;
string path = Path.Combine(Application.StartupPath, ConfigurationManager.AppSettings["ExportTemplate"]);
oXL = new Microsoft.Office.Interop.Excel.Application();
oXL.Visible = false;
oXL.DisplayAlerts = false;
mWorkBook = oXL.Workbooks.Open(path, 0, false, 5, "", "", false, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "", true, false, 0, true, false, false);
//Get all the sheets in the workbook
mWorkSheets = mWorkBook.Worksheets;
//Get the allready exists sheet
mWSheet1 = (Microsoft.Office.Interop.Excel.Worksheet)mWorkSheets.get_Item("MetaData");
Microsoft.Office.Interop.Excel.Range range = mWSheet1.UsedRange;
foreach (Excel.Worksheet oworksheet in mWorkBook.Worksheets)
{
if (oworksheet.Name == "Disicpline")
{
long fullrow = oworksheet.Rows.Count;
int rowcount = oworksheet.UsedRange.Rows.Count; //get row count
//long lastrow = oworksheet.Cells[fullrow, 1].get_End(XlDirection.xlUp).Row;
oworksheet.Cells[rowcount, 1].value = txtDiscCode.Text;
oworksheet.Cells[rowcount, 2].value = txtDiscplinName.Text;
oworksheet.Cells[rowcount, 3].value = txtDiscCode.Text + txtDiscplinName.Text;
oworksheet.Cells[rowcount, 6].value = txtDiscCode.Text;
oworksheet.Cells[rowcount, 7].value = txtDiscCode.Text;
}
}
oXL.DisplayAlerts = false;
mWorkBook.SaveAs(path, Microsoft.Office.Interop.Excel.XlFileFormat.xlWorkbookDefault, Type.Missing, Type.Missing, false, false, Excel.XlSaveAsAccessMode.xlNoChange, Excel.XlSaveConflictResolution.xlLocalSessionChanges, Type.Missing, Type.Missing,
Type.Missing, Type.Missing);
mWorkBook.Close(true, path, Type.Missing);
Marshal.ReleaseComObject(mWorkBook);
GC.Collect();
GC.WaitForPendingFinalizers();
oXL.Quit();
File is just a file:
You can use File.Exist()
if (File.Exists("ExcelFilenameHere"))
{
File.Delete("ExcelFilenameHere");
}
use it before saving
I am performing search within excel workbook using small c# application.
now, when match found I am trying to get the full row details and the bounded into datagridview as shown below, but my problem is that
get_Address(true, true, Excel.XlReferenceStyle.xlR1C1, missing, missing)
is not show in correct format within the select statement
SELECT * FROM [Sheet1$B14:I24] //correct format
SELECT * FROM [sheet$B952]
so I am getting error message says
The Microsoft Access database engine could not find the object
'sheet$B952'. Make sure the object exists and that you spell its name
and the path name correctly. If 'sheet$B952' is not a local object,
check your network connection or contact the server administrator.
I tried to use get_AddressLocal or the xlA1 style but that is wont help me
to get the correct format
please if anyone can help or provide me with better solution or scenario
Thank alot
private void B_General_Search_Click(object sender, EventArgs e)
{
Microsoft.Office.Interop.Excel.Application oXL = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel.Workbook oWB;
Microsoft.Office.Interop.Excel.Range currentFind = null;
Microsoft.Office.Interop.Excel.Range firstFind = null;
string ConnStr = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + DefaultDirectory + #"\new29.xlsx" + ";Extended Properties=\"Excel 12.0 Xml;HDR=YES\";";
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
if (string.IsNullOrEmpty(TB_Search_Text.Text))
{
MessageBox.Show("enter text for search");
return;
}
object missing = System.Reflection.Missing.Value;
oWB = oXL.Workbooks.Open(DefaultDirectory + #"\new29.xlsx", //---Filename OR FilePath
0, //---object UpdateLinks
true, //---object ReadOnly
missing, //5//---object Format
"", //---object Password
"", //---object WriteResPassword
false, //---object ReadOnlyRecommend
Excel.XlPlatform.xlWindows, //---object Origin
"", //---object Delimiter
true, //---object Editable
false, //---object Notify
0, //---object Converter
true, //---object AddToMru
false, //---object Local
false); //---object CorruptLoad;
//loop to search witin all excel sheets (workbook)
foreach (Excel.Worksheet SheetID in oWB.Worksheets)
{
Excel.Range oRng = oXL.get_Range("A1", "XFD1048576");
currentFind = oRng.Find(TB_Search_Text.Text,
missing,
Excel.XlFindLookIn.xlValues,
Excel.XlLookAt.xlPart,
Excel.XlSearchOrder.xlByRows,
Excel.XlSearchDirection.xlNext,
false,
missing,
missing);
while (currentFind != null)
{
//Keep track of the first range you find.
if (firstFind == null)
{
firstFind = currentFind;
}
else if (currentFind.get_Address(true, true, Excel.XlReferenceStyle.xlR1C1, missing, missing) == firstFind.get_Address(true, true, Excel.XlReferenceStyle.xlR1C1, missing, missing))
{
break;
}
//currentFind.Font.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Red);
//currentFind.Font.Bold = true;
currentFind = oRng.FindNext(currentFind);
//SELECT * FROM [Sheet1$B14:I24] correct format
//SELECT * FROM [sheet$B952] XXXXX
string cmdtxt = #"select * from [" + SheetID.Name + "$" + currentFind.get_Address(true, true, Excel.XlReferenceStyle.xlR1C1, missing, missing) + "]";
MessageBox.Show(cmdtxt);
using (OleDbConnection conn = new OleDbConnection(ConnStr))
{
OleDbDataAdapter DA = new OleDbDataAdapter(cmdtxt, conn);
DA.Fill(dt);
DGV_Data.DataSource = dt;
conn.Close();
}
}
}
oWB.Close(false, missing, missing);
//oSheet = null;
oWB = null;
oXL.Quit();
}
I am trying to copy an existing excel sheet into my current excel file. I am using this code.
Workbook wkActive = Globals.ThisAddIn.Application.ActiveWorkbook;
Microsoft.Office.Interop.Excel.Workbook workbook = Globals.ThisAddIn.Application.Workbooks.Open(IdsTemplatePath, 0, true, 5, "", "", true, XlPlatform.xlWindows, "\t", false, false, 0, true, false, false);
Microsoft.Office.Interop.Excel.Worksheet worksheet = workbook.Sheets[1] as Microsoft.Office.Interop.Excel.Worksheet;
worksheet.Copy(Type.Missing, wkActive);
wkActive.Save();
but when in copy method i get error
Exception from HRESULT: 0x800A03EC
what i am doing wrong and what should i do for completing my task
I got the solution
Microsoft.Office.Interop.Excel.Workbook CurrentWk
= ((Microsoft.Office.Interop.Excel.Workbook)Globals.ThisAddIn.Application.ActiveWorkbook);
if (Path.GetExtension(CurrentWk.Name) != ".xlsx")
{
MessageBox.Show("Please save the document before complete this task", "warning");
}
else
{
Microsoft.Office.Interop.Excel.Workbook workbook = Globals.ThisAddIn.Application.Workbooks.Open(IdsTemplatePath, 0, true, 5, "", "", true, XlPlatform.xlWindows, "\t", false, false, 0, true, false, false);
Microsoft.Office.Interop.Excel.Worksheet worksheet = null;
totalSheet = workbook.Worksheets.Count;
for (int sheetNum = 1; sheetNum <= totalSheet; sheetNum++)
{
worksheet = (Microsoft.Office.Interop.Excel.Worksheet)workbook.Worksheets[sheetNum];
sheetname = worksheet.Name.Replace("\r", "").Replace("\a", "").Trim().ToLower();
if (sheetname == "ids_template")
{
try
{
worksheet.Copy(CurrentWk.Sheets[1]);
workbook.Close(SaveChanges, Type.Missing, Type.Missing);
}
catch { }
ids_template_found = true;//here it is set true because template sheet is added above in current workbook.
break;
}
}
}
I am using Microsoft.Office.Interop.Excel to read an Excel file.
The problem I am having is that when reading, it counts the first row that has information as row 1. So, if the first row to have information is row 3, it counts that as the first row. This is a problem because the Excel sheets sometimes have data on the first 2 rows, sometimes they don't. But the data I need to read always starts on the third row.
Here is the routine I am using to read the sheets:
Microsoft.Office.Interop.Excel.Application exl = new Microsoft.Office.Interop.Excel.Application();
Workbooks wkbs = exl.Workbooks;
Microsoft.Office.Interop.Excel.Workbook wkb = null;
Sheets shts;
Microsoft.Office.Interop.Excel.Worksheet wks = null;
// load work book
//wkb = wkbs.Open(races_data_path, 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);//oMissing
wkb = wkbs.Open(races_data_path, Type.Missing, true, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);//oMissing
shts = wkb.Sheets;
wks = (Microsoft.Office.Interop.Excel.Worksheet)shts.get_Item(Properties.Settings.Default.excel_worksheet);
// read lines from worksheet
Microsoft.Office.Interop.Excel.Range range = wks.UsedRange;
for (int rCnt = 1; rCnt <= range.Rows.Count; rCnt++)
{
try
{
object[,] values = (object[,])range.Value2;
if (Convert.ToString(values[rCnt, 4]) != "")
{
//Console.WriteLine(String.Format("Ldd: {0} {1} {2}", Convert.ToInt16(values[rCnt, 2]), Convert.ToInt16(values[rCnt, 3]), Convert.ToString(values[rCnt, 4])));
if (races[Convert.ToInt16(values[rCnt, 1])] == null) races[Convert.ToInt16(values[rCnt, 1])] = new RaceObject();
races[Convert.ToInt16(values[rCnt, 1])].add_racer(Convert.ToInt16(values[rCnt, 2]), Convert.ToInt16(values[rCnt, 3]), Convert.ToString(values[rCnt, 4]), Convert.ToString(values[rCnt, 7]));
}
}
catch (Exception ex)
{
data_loaded = false;
rCnt = range.Rows.Count;
}
}
This example, you can see the loop count starts at '1'. This was for reading a sheet where the first 2 lines of the sheet were empty. If the first 2 lines have data, then this loop only works if I change the count start to '3'.
For example:
The start value = 1 if the sheet looks like this:
no data
no data
has data
has data
has data
The start value = 3 if the sheet looks like this:
has unnecessary data
has unnecessary data
has data
has data
has data
Option 1: Add something to the first cell immediately before doing the rest: wks.cells(1, 1).value = "'" & wks.cells(1, 1).value This will extend the usedRange to the first cell.
Then the data will always start on the third row and you can easily always skip the first two rows.
Option 2: You can also use wks.UsedRange.Cells(1, 1).Row to see whether the first row is 1 or 3. Then you can adjust whether you use those rows or not.
(Edited post based on comments)
I want to insert an Array of characters into one column of Excel. I normally use something like this to just add a normal string:
lCommand.CommandText += "\"" + row["source"].ToString().Replace("\"", "\"\"").Replace(" ", " ") + "\",";
How would I add an Array of strings to a Column of Excel? Thanks!
See this article:
Fun with Excel--setting a range of cells via an array
I recommend that you read the (short) article, but as a spoiler:
Excel.Range r = this.Range["B2", "B4"];
object[,] workingValues = new object[3, 1];
for (int i = 0; i < 3; i++)
{
workingValues[i, 0] = i + 2; // 2,3,4
}
r.Value2 = workingValues;
You can open the File with C# and write to the cell you want.
First :
using Microsoft.Office.Interop.Excel;
This require you to have COM reference for Excel.
After this you need to open the file you want and set the value. After, you can close the file.
Here is an example. You can always loop for each rows or column for your array.
_Application docExcel = new Microsoft.Office.Interop.Excel.Application();
docExcel.Visible = false;
docExcel.DisplayAlerts = false;
_Workbook workbooksExcel = docExcel.Workbooks.Open(#"C:\test.xlsx", 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);
_Worksheet worksheetExcel = (_Worksheet)workbooksExcel.ActiveSheet;
((Range)worksheetExcel.Cells["1", "A"]).Value2 = "aa";
((Range)worksheetExcel.Cells["1", "B"]).Value2 = "bb";
workbooksExcel.Save();
workbooksExcel.Close(false, Type.Missing, Type.Missing);
docExcel.Application.DisplayAlerts = true;
docExcel.Application.Quit();
Edit:
You can use the Dynamic keyword if you do not want all those Type.Missing parameter :
_Application docExcel = new Application{Visible = false};
dynamic workbooksExcel = docExcel.Workbooks.Open(#"C:\test.xlsx");
var worksheetExcel = (_Worksheet)workbooksExcel.ActiveSheet;
((Range)worksheetExcel.Cells["1", "A"]).Value2 = "test1";
((Range)worksheetExcel.Cells["1", "B"]).Value2 = "test2";
workbooksExcel.Save();
workbooksExcel.Close(false);
docExcel.Application.Quit();