I've a problem in reading data from Excel using selenium web driver. I've used "Microsoft.Office.Interop.Excel" and when running my code I found that exception
System.Runtime.InteropServices.Exception: Excel cannot access 'Downloads'. The document may be read only or encrypted.
enter image description here
This is the code I've used
public void sch_issue_1958M()
{
Application xlApp = new Application();
Workbook xlWorkBook = xlApp.Workbooks.Open(#"C:\Users\kkhatab\Desktop\3.0.0\Cube.Portal.Regression_for_issuesTests\bin\Downloads");
Worksheet xlWorkSheet = new Worksheet();
xlWorkSheet = xlWorkBook.Sheets[1];
Range xlRange = xlWorkSheet.UsedRange;
int rowCount = xlRange.Rows.Count;
int colCount = xlRange.Columns.Count;
for (int i = 1; i <= rowCount; i++)
{
for (int j = 1; j <= colCount; j++)
{
//new line
if (j == 1)
Console.Write("\r\n");
//write the value to the console
if (xlRange.Cells[i, j] != null && xlRange.Cells[i, j].Value2 != null)
Console.Write(xlRange.Cells[i, j].Value2.ToString() + "\t");
}
}
}
Just for clarity for others:
Workbook xlWorkBook = xlApp.Workbooks.Open(#"C:\Users\kkhatab\Desktop\3.0.0\Cube.Portal.Regression_for_issuesTests\bin\Downloads");
You are trying to open a folder here rather than a document.
Related
So I have a for loop that goes like this..:
for (int i = 12; i < 200; i++)
{
//Console.WriteLine(Convert.ToString(sheet01.Cells[12, 2].Value2));
if (!(string.IsNullOrEmpty(sheet01.Cells[i, 2].Value2)) && sheet01.Cells[i, 2].Value2.Length == 4)
{
Console.WriteLine(sheet01.Name);
hcnNumber.Add(Convert.ToString(sheet01.Cells[i, 2].Value2));
}
}
This code encounters an error whenever the cell [i,2] when i spans more than one column.
How can I skip rows rows that span more than one column ?
so something if row.length > 1
Thanks
I tried to work on your requirement on my local system. If I understand your requirement, You need to show only those rows where only 1st column has value, If for example a row has 10 column of which either all or more than 1 column contains data, needs to be skipped. I think it should help you a bit to reach your goal.
Below is the code which loops through and gives you the expected result.
Excel.Application xlApp = new Excel.Application();
Excel.Workbook xlWorkbook = xlApp.Workbooks.Open(#"C:\Users\acn\Desktop\CopyofFinancialSample.xlsx");
Excel._Worksheet xlWorksheet = xlWorkbook.Sheets[1];
Excel.Range xlRange = xlWorksheet.UsedRange;
int rowCount = xlRange.Rows.Count;
int colCount = xlRange.Columns.Count;
for (int i = 1; i <= rowCount; i++)
{
int count = 0;
for (int j = 1; j <= colCount; j++)
{
//add useful things here!
if (j != 1)
{
if (xlRange.Cells[i, j] != null && xlRange.Cells[i, j].Value2 != null)
{
count++;
}
}
}
if (count > 0)
{
}
else
{
if (xlRange.Cells[i, 1] != null && xlRange.Cells[i, 1].Value2 != null)
Console.WriteLine(xlRange.Cells[i, 1].Value2.ToString() + "\t");
}
}
And if you need the complete console program to test the req, Please find below
class Program
{
static void Main(string[] args)
{
//Create COM Objects. Create a COM object for everything that is referenced
Excel.Application xlApp = new Excel.Application();
Excel.Workbook xlWorkbook = xlApp.Workbooks.Open(#"C:\Users\acn\Desktop\CopyofFinancialSample.xlsx");
Excel._Worksheet xlWorksheet = xlWorkbook.Sheets[1];
Excel.Range xlRange = xlWorksheet.UsedRange;
int rowCount = xlRange.Rows.Count;
int colCount = xlRange.Columns.Count;
for (int i = 1; i <= rowCount; i++)
{
int count = 0;
for (int j = 1; j <= colCount; j++)
{
//add useful things here!
if (j != 1)
{
if (xlRange.Cells[i, j] != null && xlRange.Cells[i, j].Value2 != null)
{
count++;
}
}
}
if (count > 0)
{
}
else
{
if (xlRange.Cells[i, 1] != null && xlRange.Cells[i, 1].Value2 != null)
Console.WriteLine(xlRange.Cells[i, 1].Value2.ToString() + "\t");
}
}
//cleanup
GC.Collect();
GC.WaitForPendingFinalizers();
//rule of thumb for releasing com objects:
// never use two dots, all COM objects must be referenced and released individually
// ex: [somthing].[something].[something] is bad
//release com objects to fully kill excel process from running in the background
Marshal.ReleaseComObject(xlRange);
Marshal.ReleaseComObject(xlWorksheet);
//close and release
xlWorkbook.Close();
Marshal.ReleaseComObject(xlWorkbook);
//quit and release
xlApp.Quit();
Marshal.ReleaseComObject(xlApp);
Console.ReadLine();
}
}
}
This question already has answers here:
Format an Excel column (or cell) as Text in C#?
(10 answers)
Closed 7 years ago.
I'm trying to export Excel file by using .ToString() when I add data to a datatable. The Excel file cell format is not text but is in a General format. This my code.
public static void CreateExcel(string filename,System.Data.DataTable table)
{
if (filename != "")
{
Application xlApp = new Microsoft.Office.Interop.Excel.Application();
xlApp.DisplayAlerts = false;
if (xlApp == null)
{
return;
}
Workbook xlWorkBook;
Worksheet xlWorkSheet;
object misValue = System.Reflection.Missing.Value;
xlWorkBook = xlApp.Workbooks.Add(misValue);
xlWorkSheet = (Worksheet)xlWorkBook.Worksheets.get_Item(1);
int Row = table.Rows.Count;
int Column = table.Columns.Count;
for (int i = 0; i <= Column - 1; i++)
{
xlWorkSheet.Cells[1, i + 1] = table.Columns[i].ToString();
}
for (int i = 0; i <= Row - 1; i++)
{
for (int j = 0; j <= Column - 1; j++)
{
xlWorkSheet.Cells[i + 2, j + 1] = table.Rows[i][j].ToString();
}
}
xlWorkBook.SaveAs(#filename, Microsoft.Office.Interop.Excel.XlFileFormat.xlOpenXMLWorkbook, System.Reflection.Missing.Value, misValue, false, false, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlNoChange, Microsoft.Office.Interop.Excel.XlSaveConflictResolution.xlUserResolution, true, misValue, misValue, misValue);
xlWorkBook.Close();
xlApp.Quit();
Marshal.FinalReleaseComObject(xlWorkSheet);
Marshal.FinalReleaseComObject(xlWorkBook);
Marshal.FinalReleaseComObject(xlApp);
GC.Collect();
}
}
Are there any ways to change the cell format?
Setting the number format of cell will help you to convert cell type into text.
Excel.Worksheet ws = workBook.Worksheets[1];
ws.Range["A2"].NumberFormat = "0";
// Pull in all the cells of the worksheet
Range cells = xlWorkBook.Worksheets[1].Cells;
// set each cell's format to Text
cells.NumberFormat = "#";
Here are 2 links that will help you on every condition.
Link 1 & Link 2
In your case :
for (int i = 0; i <= Row - 1; i++)
{
for (int j = 0; j <= Column - 1; j++)
{
xlWorkSheet.Cells[i + 2, j + 1] = table.Rows[i][j].ToString();
//It will set each cell while iterates,
//I suggest, if its for all column, then set it for the excel sheet.
//or if you have a known range, then set for the range.
xlWorkSheet.Cells[i + 2, j + 1].NumberFormat = "#";
}
}
I am trying to read some spaces that are present in the excel file. Below is the format of the Excel file.
Col1 Col2 Col3
12345 11
34568 9 12
87654 10 13
I have above in once cell of the excel worksheet. When I start reading 12345, 34568.. they are all terminated by line feed.
When I start reading Col2, I can read 9 and 10, but I don't see any space before 9 and 10. Although, I can see the visible space in Col2, but it is not coming while reading the excel spreadsheet. I also tried testing the space with this function
if (!string.IsNullOrWhiteSpace(dr(0),5)
{
int j = i - 4;
rowArray[j]= dr(0,5).Text.ToString();
}
I read the whole spreadsheet in a datatable and that might be omitting the spaces.
Is there any way that I can read that space above 9.
Below is the code to read the excel file
public void getExcelFile()
{
Excel.Application xlApp = new Excel.Application();
Excel.Workbook xlWorkbook = xlApp.Workbooks.Open(#"C:\ExcelFiles\msl.xls");
Excel._Worksheet xlWorksheet = xlWorkbook.Sheets[1];
Excel.Range xlRange = xlWorksheet.UsedRange;
int rowCount = xlRange.Rows.Count;
string x;
string p;
int colCount = xlRange.Columns.Count;
for (int i = 1; i <= rowCount; i++)
{
for (int j = 1; j <= colCount; j++)
{
//new line
if (j == 1)
Console.Write("\r\n");
//write the value to the console
if (xlRange.Cells[i, j] != null && xlRange.Cells[i, j].Value2 != null)
{
x = xlRange.Cells[i, j].Value2.ToString() + "\t";
Console.Write(xlRange.Cells[i, j].Value2.ToString() + "\t");
}
}
}
Marshal.ReleaseComObject(xlRange);
Marshal.ReleaseComObject(xlWorksheet);
//close and release
xlWorkbook.Close();
Marshal.ReleaseComObject(xlWorkbook);
}
any help will be appreciated.
I am working on an application that has to convert all the valuables from each row to an rtf document. The excel file that i am using has more than 10.000 rows but only 5 columns.
so far i can read the file usingValue2.ToString method.
what i would like to do is get the 5 values from each row, provide them with a header
firsttext= the text of cel a1
secondtext= the text of cel b1
thirdtext= the text of cel c1
fourthtext= the text of cel d1
fifttext= the text of cel e1
and do the same for cel a2, b2 etc etc.
My code so far is
//Create COM Objects.
Excel.Application xlApp = new Excel.Application();
Excel.Workbook xlWorkbook = xlApp.Workbooks.Open(#"C:\aaa.xlsx");
Excel._Worksheet xlWorksheet = xlWorkbook.Sheets[1];
Excel.Range xlRange = xlWorksheet.UsedRange;
int rowCount = xlRange.Rows.Count;
int colCount = xlRange.Columns.Count;
//iterate over the rows and columns and print to the console as it appears in the file
//excel is not zero based!!
for (int i = 1; i <= rowCount; i++)
{
for (int j = 1; j <= colCount; j++)
{
//new line
if (j == 1)
Console.WriteLine("\r\n");
//write the value to the console
if (xlRange.Cells[i, j] != null && xlRange.Cells[i, j].Value2 != null)
Console.Write(xlRange.Cells[i, j].Value2.ToString() + "\t", "\r\n");
}
// Console.ReadLine(); for testing purposes
}
//cleanup
GC.Collect();
GC.WaitForPendingFinalizers();
// rule of thumb for releasing com objects:
// never use two dots, all COM objects must be referenced and released individually
// ex: [somthing].[something].[something] is bad
//release com objects to fully kill excel process from running in the background
Marshal.ReleaseComObject(xlRange);
Marshal.ReleaseComObject(xlWorksheet);
//close and release
xlWorkbook.Close();
Marshal.ReleaseComObject(xlWorkbook);
//quit and release
xlApp.Quit();
Marshal.ReleaseComObject(xlApp);
Console.ReadLine();
any help would be appreciated
I'm still not really sure what your problem is?
Are you just asking on how to add the headers?
//iterate over the rows and columns and print to the console as it appears in the file
//excel is not zero based!!
for (int i = 1; i <= rowCount; i++)
{
for (int j = 1; j <= colCount; j++)
{
//new line
if (j == 1)
Console.WriteLine("\r\n");
//write the value to the console
if (xlRange.Cells[i, j] != null && xlRange.Cells[i, j].Value2 != null)
Console.Write("{0}= ", GetHeaderText(j));
Console.Write(xlRange.Cells[i, j].Value2.ToString() + "\t", "\r\n");
}
// Console.ReadLine(); for testing purposes
}
Get the header text via some helper method:
private string GetHeaderText(int colId)
{
switch (colId)
{
case 1:
return "firsttext";
case 2:
return "secondtext";
case 3:
return "thirdtext";
case 4:
return "fourthtext";
case 5:
return "fithtext";
default:
return "header not defined";
}
}
I'm using this function to export a data table into excel.
protected void ExportExcel(System.Data.DataTable dt)
{
if (dt == null||dt.Rows.Count==0) return;
Microsoft.Office.Interop.Excel.Application xlApp =
new Microsoft.Office.Interop.Excel.Application();
if (xlApp == null)
{
return;
}
System.Globalization.CultureInfo CurrentCI =
System.Threading.Thread.CurrentThread.CurrentCulture;
System.Threading.Thread.CurrentThread.CurrentCulture =
new System.Globalization.CultureInfo("en-US");
Microsoft.Office.Interop.Excel.Workbooks workbooks = xlApp.Workbooks;
Microsoft.Office.Interop.Excel.Workbook workbook =
workbooks.Add(Microsoft.Office.Interop.Excel.XlWBATemplate.xlWBATWorksheet);
Microsoft.Office.Interop.Excel.Worksheet worksheet =
(Microsoft.Office.Interop.Excel.Worksheet)workbook.Worksheets[1];
Microsoft.Office.Interop.Excel.Range range;
long totalCount = dt.Rows.Count;
long rowRead = 0;
float percent = 0;
for (int i = 0; i < dt.Columns.Count; i++)
{
worksheet.Cells[1, i + 1] = dt.Columns[i].ColumnName;
range = (Microsoft.Office.Interop.Excel.Range)worksheet.Cells[1, i + 1];
range.Interior.ColorIndex = 15;
range.Font.Bold = true;
}
for (int r = 0; r < dt.Rows.Count; r++)
{
for (int i = 0; i < dt.Columns.Count; i++)
{
worksheet.Cells[r + 2, i + 1] = dt.Rows[r][i].ToString();
}
rowRead++;
percent = ((float)(100 * rowRead)) / totalCount;
}
xlApp.Visible = true;
}
As you can see in the resulting excel image, the columns are not properly formatted i.e., the column sizes do not adapt to the databound items. How will I make the excel cells auto-adjust according to the data table?
And I also would like to add some text, maybe a header, for say maybe "System.DateTime.Now" or "data table name". How do i do this?
You should be able to format the columns like so:
Microsoft.Office.Interop.Excel.Range columns = worksheet.UsedRange.Columns;
columns.AutoFit();
You can insert a new row and place the current date as the title like so:
worksheet.Rows[1].Insert();
Excel.Range newRow = worksheet.Rows[1];
Excel.Range newCell = newRow.Cells[1];
newCell.Value = DateTime.Now.ToString("yyyy-MM-dd");
Also add this to your using statements so you don't need to use the fully qualified name every time you use an Excel object:
using Excel = Microsoft.Office.Interop.Excel;
Also, I have tidied up your method, by adding a few using statements to reduce clutter, removing some unnecessary casting and an unnesscessary check for null on the application object, just after it had been assigned:
using Excel = Microsoft.Office.Interop.Excel;
using System.Globalization;
using System.Threading;
using System.Data;
protected void ExportExcel(DataTable dt)
{
if (dt == null || dt.Rows.Count == 0) return;
var xlApp = new Excel.Application();
//Is this used?
CultureInfo CurrentCI = Thread.CurrentThread.CurrentCulture;
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
Excel.Workbooks workbooks = xlApp.Workbooks;
Excel.Range range
Excel.Workbook workbook = workbooks.Add();
Excel.Worksheet worksheet = workbook.Worksheets[1];
long totalCount = dt.Rows.Count;
long rowRead = 0;
float percent = 0;
for (var i = 0; i < dt.Columns.Count; i++)
{
worksheet.Cells[1, i + 1] = dt.Columns[i].ColumnName;
range = worksheet.Cells[1, i + 1];
range.Interior.ColorIndex = 15;
range.Font.Bold = true;
}
for (var r = 0; r < dt.Rows.Count; r++)
{
for (var i = 0; i < dt.Columns.Count; i++)
{
worksheet.Cells[r + 2, i + 1] = dt.Rows[r][i].ToString();
}
rowRead++;
//is this used?
percent = ((float)(100 * rowRead)) / totalCount;
}
Microsoft.Office.Interop.Excel.Range columns = worksheet.UsedRange.Columns;
columns.AutoFit();
worksheet.Rows[1].Insert();
Excel.Range newRow = worksheet.Rows[1];
Excel.Range newCell = newRow.Cells[1];
newCell.Value = DateTime.Now.ToString("yyyy-MM-dd");
xlApp.Visible = true;
}