I have an excel sheet which contains around 1000 lines of data, i have copy these data to another sheet which satisfy the condition. In order to achieve this i have written a script,
For m = 1 To x2 'iterate single column
For n = 1 To x4 'iterate PM_DUMP
If InStr(PMSheet.cells(n,6).value, dupSingle.cells(m,1).value) > 0 Then
' For p = 1 To y4
wsc.Activate
wsc.Rows.Item(n).Select
wsc.Application.Selection.Copy
wsb.Activate
wsb.Rows(m).Select
wsb.paste
wsc.Application.CutCopyMode = False
On Error Resume Next
Exit For
End If
Next
Next
GetExcel2.Save
The execution of the script goes well up to certian limit say 350 rows the next row was getting copied fine but the entire row was highlight in Red Color after few minutes, I am getting an error " An EXCEL Encountered an error " then it closes the workbook and opens a new sheet without any data...
Any help to resolve this issue is much appreciated.
With Regards,
Ramesh.T
Try combining the copy and pasting into a single step. Replace all this code
wsc.Activate
wsc.Rows.Item(n).Select
wsc.Application.Selection.Copy
wsb.Activate
wsb.Rows(m).Select
wsb.paste
wsc.Application.CutCopyMode = False
wsc.Application.CutCopyMode = False
On Error Resume Next
with
wsc.Rows(n).Copy wsb.Rows(m)
I have, on occasion, found it simpler to deal with Excel data through an OLEDB interface. Then you simply treat two sheets as two tables, with standard DataTable operations instead of the more fickle Automation operations. I only have a ready example for reading data, but hopefully you can extrapolate writing operations as well:
/// <summary>
/// Reads an Excel spreadsheet into a new DataTable.
/// </summary>
/// <param name="xlsFile">The full file path of the Excel workbook to read from.</param>
/// <param name="sheetName">The name of the sheet in the workbook to read.</param>
/// <param name="tableName">The name to give the new DataTable that the spreadsheet is read into.</param>
/// <param name="firstRowIsHeader">Indicates wheather or not the first row of the spreadsheet is a header row.</param>
/// <returns></returns>
internal static DataTable XlsToDataTable(string xlsFile, string sheetName, string tableName, bool firstRowIsHeader)
{
var dt = new DataTable(tableName);
var yesNo = firstRowIsHeader ? "Yes" : "No";
string connStr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + xlsFile + ";Extended Properties='Excel 8.0;HDR=" + yesNo + ";IMEX=1';";
using (var ocn = new OleDbConnection(connStr ))
{
var cmd = new OleDbCommand("Select * from [" + sheetName + "$]", ocn);
var datadapt = new OleDbDataAdapter {SelectCommand = cmd};
datadapt.Fill(dt);
}
return dt;
}
It's my experience that the .Paste doesn't work that well, so I'd recommend that you change
wsb.paste
to
wsb.pastespecial
Do you still have problems if you change that?
UPDATE:
I'm not sure if this will make any difference in the execution, but I think the middle section is more complicated than it needs to be - does it work if you replace the middle section of the loop with this code:
wsc.Activate
wsc.Rows(m).Item.Copy
wsb.Activate
wsb.Rows(n).PasteSpecial
That way, you also won't need to set the CutCopyMode = False until you're totally done with the loops, so it should be faster.
Related
my question about import excel to datagridview but there is an extra case.
I have also a oledb database with store code and store names.
I want it to show only store codes from db that are in the database after imported.
my codes here;
Dim conn As OleDbConnection
Dim dtr As OleDbDataReader
Dim dta As OleDbDataAdapter
Dim cmd As OleDbCommand
Dim dts As DataSet
Dim excel As String
Dim OpenFileDialog As New OpenFileDialog
OpenFileDialog1.FileName = ""
OpenFileDialog1.InitialDirectory = My.Computer.FileSystem.SpecialDirectories.Desktop
OpenFileDialog1.Filter = "All Files (*.*)|*.*|Excel files (*.xlsx)|*.xlsx|CSV Files (*.csv)|*.csv|XLS Files (*.xls)|*xls"
If (OpenFileDialog1.ShowDialog(Me) = System.Windows.Forms.DialogResult.OK) Then
DataGridView1.Columns.Clear()
Dim fi As New FileInfo(OpenFileDialog1.FileName)
Dim FileName As String = OpenFileDialog1.FileName
excel = fi.FullName
conn = New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + excel + ";Extended Properties=Excel 12.0;")
dta = New OleDbDataAdapter("Select * From [Sheet1$]", conn)
dts = New DataSet
dta.Fill(dts, "[Sheet1$]")
DataGridView1.DataSource = dts
DataGridView1.DataMember = "[Sheet1$]"
conn.Close()
End If
firstly sorry for my terrible english :)
images as follows;
Main Form
Store List Form
I want only the ones in the store list to be displayed in datagrid.. :\
It's not exactly clear what your current presentation/display looks like, what the problem is, and what your desired presentation/display should look like. But you have asked about selecting only one part of the data you are importing, which is presumably found in only one column of the imported Excel data.
When the datatable is created, it has the columns and rows from the Excel worksheet. The columns will be data from the first row, and the rows will be the records from the succeeding rows in the worksheet. You can access both the header data and the row data easily. The code below is VERY rough but for you to see how to gain access to the data in the datatable which you have already very successfully imported in the limited code shown above.
Dim columns = datatable.Columns
Dim rows = datatable.Rows
Dim columns1 = columns(0)
Dim rows1 = rows(0)
Dim element1 = rows1(0)
Columns will have all the headers, so you can locate the column with the store codes or store names. Then the rows will have the data for each store. So above, rows1 is the first row of data and element1 is the data in that row from columns1, and so on. The (0) is the index into the respective collections.
You will, of course, have to write code to extract the data you want and if necessary eliminate duplicates, but the data is all there already.
Hopefully getting the data into a list and then sorting, filtering and selecting the data should be relatively straightforward, but if not, add a comment. That's kind of a different problem. You asked about getting only the store codes.
Added: Based on your additional images and explanation, you are looking to perform an SQL INNER JOIN operation. From the w3schools.com page on SQL INNER JOIN, "The INNER JOIN keyword selects all rows from both tables as long as there is a match between the columns." This is something you will have to study and learn, but it should provide what you need in this case. You will need to define and construct both tables and then perform the JOIN.
And, by the way, you could also follow the link provided in the first comment by T.S., and if that solves your problem, it's a far simpler solution.
When trying to get the Input the data from the Excel Sheet while working with OATS tool, it always gets into the catch block of the function. The below is the script written. Please help us resolve this issue.
public String getInputfromExcel(int argColumnNumber,int argRowNumber)throws Exception
{
String inputExcelName = dataPath+".xlsx";
String cellContent = "12";
try
{
Workbook workbook = Workbook.getWorkbook(new File(inputExcelName));
Sheet sheet = workbook.getSheet(0);
Cell a1 = sheet.getCell(argColumnNumber, argRowNumber);
cellContent = (a1.getContents()).toString();
System.out.println(cellContent.toString());
workbook.close();
}
catch (Exception e)
{
addReport("Getting Input From Excel", "Fail","Exception while reading value from excel sheet");
}
return cellContent;
}
Axel has brought up the point. On a further note, if I remember correctly, the function sheet.getCell(arg1, arg2) has first argument as rowNumber and 2nd as columnNumber (both the values are 0 based index).
Its old quetion....but just posting answer it might be helpful for someone needy.
In Oracle Application Testing Suite. NO NEED of external JARs to read/write data.
You can enable DataTable module in the tool
Complete explanation given here, http://www.testinghive.com/how-to-read-write-excel-in-oats/
//Define Sheet name to be read, and provide comma seperated to read multiple sheets
String sheetName = "Sheet1";
//Mention excel sheet path
String strFile= "C:\\Demo\\test.xls";
//Defined array list to add Sheets to read
List sheetList = new ArrayList();
sheetList.add(sheetName);
// Iports Sheet1
datatable.importSheets(strFile, sheetList, true, true);
//get rowcount
info("Total rows :"+datatable.getRowCount());
int rowcount=datatable.getRowCount();
//Loop to read all rows
for (int i=0;i<rowcount;i++)
{
//Set current row fromw here you need to start reading, in this case start from first row
datatable.setCurrentRow(sheetName, i);
String strCompany=(String) datatable.getValue(sheetName,i,"Company");
String strEmpFName=(String) datatable.getValue(sheetName,i,"FirstName");
String strEmpLName=(String) datatable.getValue(sheetName,i,"LastName");
String strEmpID=(String) datatable.getValue(sheetName,i,"EmpID");
String strLocation=(String) datatable.getValue(sheetName,i,"Location");
//prints first name and last name
System.out.println("First Name : "+strEmpFName+", Last Name : "+strEmpLName);
//Sets ACTIVE column in excel sheet to Y
String strActive="Y";
datatable.setValue(sheetName, i, datatable.getColumn(sheetName, datatable.getColumnIndex("Active")), strActive);
}
//Updates sheet with updated values ie ACTIVE column sets to Y
datatable.exportToExcel("C:\\Demo\\test1.xlsx");
Currently I have an application that takes information from a SQLite database and puts it to Excel. However, I'm having to take each DataRow, iterate through each item, and put each value into it's own cell and determine highlighting. What this is causing is 20 minutes to export a 9000 record file into Excel. I'm sure it can be done quicker than that. My thoughts are that I could use a data source to fill the Excel Range and then use the column headers and row numbers to format only those rows that need to be formatted. However, when I look online, no matter what I seem to type, it always shows examples of using Excel as a database, nothing about importing into excel. Unless I'm forgetting a key word or to. Now, this function has to be done in code as it's part of a bigger application. Otherwise I would just have Excel connect to the DB and pull the information itself. Unfortunately that's not the case. Any information that could assist me in quick loading an excel sheet would be appreciated. Thanks.Additional Information:Another reason why the pulling of the information from the DB has to be done in code is that not every computer this is loaded on will have Excel on it. The person using the application may simply be told to export the data and email it to their supervisor. The setup app includes the needed dlls for the application to make the proper format.Example Code (Current):
For Each strTemp In strColumns
excelRange = worksheet.Cells(1, nCounter)
excelRange.Select()
excelRange.Value2 = strTemp
excelRange.Interior.Color = System.Drawing.Color.Gray.ToArgb()
excelRange.BorderAround(Excel.XlLineStyle.xlContinuous, Excel.XlBorderWeight.xlThin, Excel.XlColorIndex.xlColorIndexAutomatic, Type.Missing)
nCounter += 1
Next
Now, this is only example code in terms of the iteration I'm doing. Where I'm really processing the information from the database I'm iterating through a dataTable's Rows, then iterating through the items in the dataRow and doing essentially the same as above; value by value, selecting the range and putting the value in the cell, formatting the cell if it's part of a report (not always gray), and moving onto the next set of data. What I'd like to do is put all of the data in the excel sheet (A2:??, not a row, but multiple rows) then iterate through the reports and format each row then. That way, the only time I iterate through all of the records is when every record is part of a report.
Ideal Code
excelRange = worksheet.Cells("A2", "P9000")
excelRange.DataSource = ds 'ds would be a queried dataSet, and I know there is no excelRange.DataSource.
'Iteration code to format cells
Update:
I know my examples were in VB, but it's because I was also trying to write a VB version of the application since my boss prefers VB. However, here's my final code using a Recordset. The ConvertToRecordset function was obtained from here.
private void CreatePartSheet(Excel.Worksheet excelWorksheet)
{
_dataFactory.RevertDatabase();
excelWorksheet.Name = "Part Sheet";
string[] strColumns = Constants.strExcelPartHeaders;
CreateSheetHeader(excelWorksheet, strColumns);
System.Drawing.Color clrPink = System.Drawing.Color.FromArgb(203, 192, 255);
System.Drawing.Color clrGreen = System.Drawing.Color.FromArgb(100, 225, 137);
string[] strValuesAndTitles = {/*...Column Names...*/};
List<string> lstColumns = strValuesAndTitles.ToList<string>();
System.Data.DataSet ds = _dataFactory.GetDataSet(Queries.strExport);
ADODB.Recordset rs = ConvertToRecordset(ds.Tables[0]);
excelRange = excelWorksheet.get_Range("A2", "ZZ" + rs.RecordCount.ToString());
excelRange.Cells.CopyFromRecordset(rs, rs.RecordCount, rs.Fields.Count);
int nFieldCount = rs.Fields.Count;
for (int nCounter = 0; nCounter < rs.RecordCount; nCounter++)
{
int nRowCounter = nCounter + 2;
List<ReportRecord> rrPartReports = _lstReports.FindAll(rr => rr.PartID == nCounter).ToList<ReportRecord>();
excelRange = (Excel.Range)excelWorksheet.get_Range("A" + nRowCounter.ToString(), "K" + nRowCounter.ToString());
excelRange.Select();
excelRange.NumberFormat = "#";
if (rrPartReports.Count > 0)
{
excelRange.Interior.Color = System.Drawing.Color.FromArgb(230, 216, 173).ToArgb(); //Light Blue
foreach (ReportRecord rr in rrPartReports)
{
if (lstColumns.Contains(rr.Title))
{
excelRange = (Excel.Range)excelWorksheet.Cells[nRowCounter, lstColumns.IndexOf(rr.Title) + 1];
excelRange.Interior.Color = rr.Description.ToUpper().Contains("TAG") ? clrGreen.ToArgb() : clrPink.ToArgb();
if (rr.Description.ToUpper().Contains("TAG"))
{
rs.Find("PART_ID=" + (nCounter + 1).ToString(), 0, ADODB.SearchDirectionEnum.adSearchForward, "");
excelRange.AddComment(Environment.UserName + ": " + _dataFactory.GetTaggedPartPrevValue(rs.Fields["POSITION"].Value.ToString(), rr.Title));
}
}
}
}
if (nRowCounter++ % 500 == 0)
{
progress.ProgressComplete = ((double)nRowCounter / (double)rs.RecordCount) * (double)100;
Notify();
}
}
rs.Close();
excelWorksheet.Columns.AutoFit();
progress.Message = "Done Exporting to Excel";
Notify();
_dataFactory.RestoreDatabase();
}
Can you use ODBC?
''http://www.ch-werner.de/sqliteodbc/
dbName = "c:\docs\test"
scn = "DRIVER=SQLite3 ODBC Driver;Database=" & dbName _
& ";LongNames=0;Timeout=1000;NoTXN=0;SyncPragma=NORMAL;StepAPI=0;"
Set cn = CreateObject("ADODB.Connection")
cn.Open scn
Set rs = CreateObject("ADODB.Recordset")
rs.Open "select * from test", cn
Worksheets("Sheet3").Cells(2, 1).CopyFromRecordset rs
BTW, Excel is quite happy with HTML and internal style sheets.
I have used the Excel XML file format in the past to write directly to an output file or stream. It may not be appropriate for your application, but writing XML is much faster and bypasses the overhead of interacting with the Excel Application. Check out this Introduction to Excel XML post.
Update:
There are also a number of libraries (free and commercial) which can make creating excel document easier for example excellibrary which doesn't support the new format yet. There are others mentioned in the answers to Create Excel (.XLS and .XLSX) file from C#
Excel has the facility to write all the data from a ADO or DAO recordset in a single operation using the CopyFromRecordset method.
Code snippet:
Sheets("Sheet1").Range("A1").CopyFromRecordset rst
I'd normally recommend using Excel to pull in the data from SQLite. Use Excel's "Other Data Sources". You could then choose your OLE DB provider, use a connection string, what-have-you.
It sounds, however, that the real value of your code is the formatting of the cells, rather than the transfer of data.
Perhaps refactor the process to:
have Excel import the data
use your code to open the Excel spreadsheet, and apply formatting
I'm not sure if that is an appropriate set of processes for you, but perhaps something to consider?
Try this out:
http://office.microsoft.com/en-au/excel-help/use-microsoft-query-to-retrieve-external-data-HA010099664.aspx
Perhaps post some code, and we might be able to track down any issues.
I'd consider this chain of events:
query the SQLite database for your dataset.
move the data out of ADO.NET objects, and into POCO objects. Stop using DataTables/Rows.
use For Each to insert into Excel.
I'm working on a SharePoint workflow, and the first step requires me to open an Excel workbook and read two things: a range of categories (from a range named, conveniently enough, Categories) and a category index (in the named range CategoryIndex). Categories is a list of roughly 100 cells, and CategoryIndex is a single cell.
I'm using ADO.NET to query the workbook
string connectionString =
"Provider=Microsoft.ACE.OLEDB.12.0;" +
"Data Source=" + temporaryFileName + ";" +
"Extended Properties=\"Excel 12.0 Xml;HDR=YES\"";
OleDbConnection connection = new OleDbConnection(connectionString);
connection.Open();
OleDbCommand categoryIndexCommand = new OleDbCommand();
categoryIndexCommand.Connection = connection;
categoryIndexCommand.CommandText = "Select * From CategoryIndex";
OleDbDataReader indexReader = categoryIndexCommand.ExecuteReader();
if (!indexReader.Read())
throw new Exception("No category selected.");
object indexValue = indexReader[0];
int categoryIndex;
if (!int.TryParse(indexValue.ToString(), out categoryIndex))
throw new Exception("Invalid category manager selected");
OleDbCommand selectCommand = new OleDbCommand();
selectCommand.Connection = connection;
selectCommand.CommandText = "SELECT * FROM Categories";
OleDbDataReader reader = selectCommand.ExecuteReader();
if (!reader.HasRows || categoryIndex >= reader.RecordsAffected)
throw new Exception("Invalid category/category manager selected.");
connection.Close();
Don't judge the code itself too harshly; it's been through a lot. Anyway, the first command never executes correctly. It doesn't throw an exception. It just returns an empty data set. (HasRows is true, and Read() returns false, but there is no data there) The second command works perfectly. These are both named ranges.
They are populated differently, however. There's a web service call that fills up Categories. Those values are displayed in a dropdown box. The selected index goes into CategoryIndex. After hours of banging my head, I decided to write a couple of lines of code so that the dropdown's value goes into a different cell, then I copy the value using a couple of lines of C# into CategoryIndex, so that the data is set identically. That turned out to be a blind alley, too.
Am I missing something? Why would one query work perfectly and the other fail to return any data?
I have found the issue. Excel was apparently unable to parse the value in the cell, so it was returning nothing. What I had to do was adjust the connection string to the following:
string connectionString =
"Provider=Microsoft.ACE.OLEDB.12.0;" +
"Data Source=" + temporaryFileName + ";" +
"Extended Properties=\"Excel 12.0 Xml;HDR=NO;IMEX=1\"";
It would have been helpful if it would have thrown an exception or given any indication of why it was failing, but that's beside the point now. The option IMEX=1 tells Excel to treat all values as strings only. I'm quite capable of parsing my own integers, thankyouverymuch, Excel, so I didn't need its assistance.
I have one problem. I need to get the excel sheet name in a work book, which looks on the very left sheets tab -the first one from my point of view.
I am using this code:
public static string GetFirstExcelSheetName(OleDbConnection connToExcel)
{
DataTable dtSheetName =
connToExcel.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
List<String> lstExcelSheet = new List<string>(dtSheetName.Rows.Count);
foreach (DataRow row in dtSheetName.Rows)
lstExcelSheet.Add(row["TABLE_NAME"].ToString());
return lstExcelSheet[0];
}
The problem here is it is returning the rows not in the visual tab order but in a very different order - most probably the row created date.
How can it be possible to get the sheetnames table ordered according to their tab order so that I can easily get the 1st excel sheet name?
Thanks,
kalem keki
It should be the zero-th item in the workbooks(?) collection.
I think you have the right index, wrong collection.
Sorry, didn't notice you're using the rows collection of a datatable.
That's a different problem.
How do you create the datatable?
You might have to change the sort property of the dataview.
Dim dtSheetnames As DataTable = oleDBExcelConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, New Object() {Nothing, Nothing, Nothing, "TABLE"})
Dim FirstSheetName As String = dtSheetnames.Rows(0)!TABLE_NAME.ToString
The row 0 is not the first sheet in the excel file, rows are sorted by alphabetical order in this collection :/
I recommend using the NPOI library (http://npoi.codeplex.com/) rather than OleDB to retrieve data (including metadata) from Excel.
IIRC, OleDB will also fail for sheet names that include spaces or dollar signs.
OleDbConnection oconn = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + Session["path"].ToString() + "; Extended Properties=Excel 12.0;Persist Security Info=False;");
oconn.Open();
myCommand.Connection = oconn;
DataTable dbSchema = oconn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
if (dbSchema == null || dbSchema.Rows.Count < 1)
{
throw new Exception("Error: Could not determine the name of the first worksheet.");
}
string firstSheetName = dbSchema.Rows[0]["TABLE_NAME"].ToString();