C# Inserting Rows from DataTable to Excel Spreadsheet - c#

Is there a way to add rows from a DataTable to a Excel spreadsheet without interating through a SQL Insert Statement as so? Are there any alternative methods?
foreach (DataRow drow in DataTable DT)
{
cmd.CommandText = "INSERT INTO [LHOME$]([Date], [Owner], [MAKE], [BUY],
[OVERAGE], [SUM]) " + "VALUES(" + "'" + drr.ItemArray[0].ToString() + "'" + "," + "'" + drr.ItemArray[1].ToString() + "'" + "," + "'" + drr.ItemArray[2].ToString() +
I'm trying to work around the DataTypes going into Excel worksheet. Because all my numbers which are saved as string are being inserted as a text with a conversion prompt on each cell. When I write to the worksheet as is. The dataTypes are all Strings. But I'm looking for a way that I don't have to specify the DataType. If there was a way to just push my changes from a DataTable and commit my changes to the spreadsheet.

Here's a shot in the dark, as I've never used IronPython and you may be asking for a C# specific solution. You could try using IronPython here and using this Python library made for accessing excel:
http://www.python-excel.org/
Here's some example code to get a feel for how easy it is to work with:
import xlwt
wb = xlwt.Workbook()
ws = wb.add_sheet('A Test Sheet')
ws.write(2, 0, 1)
ws.write(2, 1, 1)
wb.save('example.xls')
I'm not sure what problem you're trying to solve, but maybe this can help you out.

Related

How can add new row without insert with ado.net

stokService = new StokService();
var stok = stokService.stokList("Select * from xstSabit where stokKodu= '" + txtStokKodu.Text + "' ");
dgvSepet.DataSource = stok;
this stok selected and viewed in Datagridview there is no problem. I want to add one more stok to Datagridview with existing stok but in this code it is only return one stok. How can ı add new rows without insert ?
As far as I know this is impossible. The alternative would be to upgrade an existing row if inserting new raw is not so mandatory.

SQL cannot read slash from Excel import

I import fuel transactions from an Excel file into an SQL database.
One column from the Excel is giving me trouble: "product synonym"
// Match to product
FuelProductTypeSynonym typeSyn = ctx.FuelProductTypeSynonym.SingleOrDefault(s => s.Name.ToUpper() == row.Product.ToUpper());
if (typeSyn == null)
{
result.Errors.Add("[" + fileName + "] (row " + currentRow + "): product match not found.");
}
If the product synonym doesn't match what's in the database, the program stops. In my case, I have a product "FOOD/BEVERAGE" and it seems like the "/" portion of the name can't be parsed from Excel.
How do I get around this "/" so SQL understands that name?

Is there an easy way to remove/ignore rows above column names in an Excel file using OleDbConnection?

I have code like this for reading an Excel file:
string connStr = "Provider=Microsoft.ACE.OLEDB.12.0;" +
"Data Source=" + path + ";Extended Properties=\"Excel 12.0;HDR=YES\";";
using (OleDbConnection conn = new OleDbConnection(connStr))
{
conn.Open();
DataTable dtSchema = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });
string sheetName = dtSchema.Rows[0].Field("TABLE_NAME");
OleDbDataAdapter sheetAdapter = new OleDbDataAdapter("select * from [" + sheetName + "]", conn);
sheetAdapter.Fill(sheetData);
DataTable dtColumns = conn.GetSchema("Columns", new string[] { null, null, sheetName, null });
...
}
My code needs to use/look at the column headers. The above only works if the column headers are the first row. Sometimes the Excel files that we receive from clients have a couple rows above the column headers with some metadata about the data in the excel. When this happens the column headers will be on something like row 10.
I can open the Excel file and manually delete the extra rows above the column headers and this solves the issue. But we want to remove this manual step.
Is there any easy way to remove/ignore these extra starting rows above the column headers? Or do I have to come up with custom code? The best way I can think of is to turn off HDR and then the first row that has a value in every column is the column header row. Is there an easier way?
I have code that reads from Excel, needs to ignore the first 11 rows in the worksheet, and read from columns A through P for up to 64000 rows.
// Read columns A - P after skipping 11 rows to read the header row
string ExcelDataQuery = string.Concat("SELECT * FROM [", sheetname, "A12:P64012]");
As far as i know (checked that issue in the past) there is no way to select a table with System.Data.OleDb from excel file using SQL query if headers are not placed in row 1. the solution for me (like you do) is to delete all the rows above the header row before querying the worksheet - just opening the workbook with Microsoft.Office.Interop deleting the extra rows, closing it and than querying it.
Excel is a very powerful tool but was never designed to behave like database (SQL \ access file for example).

Column missing from excel spreedshet

I have a list of invoices that and I transferred them to an Excel spreadsheet.
All the columns are created into the spreadsheet except for the Job Date column. That is blank in the spreadsheet.
Here's the code:
string Directory = ConfigurationSettings.AppSettings["DownloadDestination"] + Company.Current.CompCode + "\\";
string FileName = DataUtils.CreateDefaultExcelFile(Company.Current.CompanyID, txtInvoiceID.Value, Directory);
FileInfo file = new FileInfo(FileName);
Response.Clear();
Response.ContentType = "application/x-download";
Response.AddHeader("Content-Length", file.Length.ToString());
Response.AddHeader("Content-Disposition", "attachment; filename=" + file.Name);
Response.CacheControl = "public";
Response.TransmitFile(file.FullName);
Response.Flush();
Context.ApplicationInstance.CompleteRequest();
public static string CreateDefaultExcelFile(int CompanyID, string InvoiceNo, string CreateDirectory)
{
List<MySqlParameter> param = new List<MySqlParameter>{
{ new MySqlParameter("CompanyID", CompanyID) },
{ new MySqlParameter("InvoiceNo", InvoiceNo) }
};
DataTable result = BaseDisplaySet.CustomFill(BaseSQL, param);
string FileName = CreateDirectory + "InvoiceFile_" + DateTime.Now.ToString("yyyyMMddhhmmssff") + ".";
FileName += "xlsx";
XLWorkbook workbook = new XLWorkbook();
workbook.Worksheets.Add(result, "Bulk Invoices");
workbook.SaveAs(FileName);
return FileName;
}
private const string BaseSQL = " SELECT q.InvoiceNo AS InvoiceNumber, j.JobNo, j.JobDate AS JobDate, " +
" (SELECT Name FROM job_address WHERE AddressType = 6 AND JobID = j.ID LIMIT 0,1) AS DebtorName, " +
" (SELECT CONCAT(Name,CONCAT(',',Town)) FROM job_address WHERE AddressType = 3 AND JobID = j.ID LIMIT 0,1) AS CollectFrom, " +
" (SELECT CONCAT(Name,CONCAT(',',Town)) FROM job_address WHERE AddressType = 2 AND JobID = j.ID LIMIT 0,1) AS DeliverTo, " +
" deladd.Town AS DeliverToTown, deladd.County AS DeliveryToCounty, " +
" (SELECT DocketNo FROM job_dockets WHERE JobID = j.ID LIMIT 0,1) AS DocketNo, " +
" SUM(j.DelAmt) AS DelAmount, " +
" (SELECT CAST(group_concat(DISTINCT CONCAT(AdvisedQty,' ',PieceType) separator ',') AS CHAR(200)) FROM job_pieces WHERE JobID = j.ID GROUP BY JobID ) AS PieceBreakDown " +
" FROM Invoice q " +
" LEFT JOIN customer c ON q.accountcode = c.ID " +
" INNER JOIN job_new j ON q.JobID = j.ID " +
" LEFT JOIN job_address coladd ON coladd.JobID = j.ID AND coladd.AddressType = 3 " +
" LEFT JOIN job_address deladd ON deladd.JobID = j.ID AND deladd.AddressType = 2 " +
" WHERE q.IsActive = 1 AND q.Company_ID = ?CompanyID AND q.InvoiceNo = ?InvoiceNo " +
" group by j.id";
The sql returns all the correct information and as you can see the job date is there:
But when I open the Excel file after it is created, the job date column is blank:
You should convert JobDate in BaseSQL to string.
A sample example is given below. You can use it to get an idea how to convert datetime to varchar.
DECLARE #myDateTime DATETIME
SET #myDateTime = '2008-05-03'
--
-- Convert string
--
SELECT LEFT(CONVERT(VARCHAR, #myDateTime, 120), 10)
I don't know what framework do you use to export data to excel and how powerful it is, but I do know that Excel does not directly support dates (surprise!), at least not in xml-based (OpenXml) xlsx documents. It works only with strings and numbers (which are saved in underlying document as string and number literals)
Considering that, you can use simple workaround: convert your dates to strings via either cast/convert in sql or ToString() in C#. You will loose Excel date functionality (like date filters, custom formats), obviously.
However, it is not an only way (cheers!). You can save your data in the same way Excel stores it. If your framework does not support it, you will have to do it yourself: the recipe will be the same as with creation xlsx documents by hand with DocumentFormat.OpenXml.dll.
Actually, Excel uses "OLE-Automation Date" format as internal representation for dates, which is implemented as a floating-point number whose integral component is the number of days before or after midnight, 30 December 1899, and whose fractional component represents the time on that day divided by 24. This representation is stored in document as number literal. Excel distinguishes dates and numbers by numbering format of corresponding cell. With that in mind, you can use not so simple workaround:
First, convert your dates to numbers:
DateTime date = DateTime.Now;
double dateValue = date.ToOADate();
//or
TimeSpan time = DateTime.Now.TimeOfDay;
double timeValue = (DateTime.FromOADate(0) + time).ToOADate();
Then double variable should be set to CellValue of Excel Cell, you can create new column with double datatype in DataTable, fill it using this transformation, then drop original DateTime column.
Second, apply date format to desired cells. Unfortunately, required code will differ between frameworks, but the principle should be the same:
Locate corresponding cell range (either CellRange or Cells, maybe Columns)
Set date format string (via something like range.NumberFormat.Format="dd/mm/yyyy" or range.NumberFormatString="dd/mm/yyyy")
If, however, this framework does not support simplified formatting (very strange framework that will be), you will have to either set range.NumberFormatId=22 for standard date format or create new number format. If you are rather unlucky and this framework is as simple as DocumentFormat.OpenXml, you will have to create custom CellFormat with correspoding NumberFormatId (22 or id of custom NumberFormat), add it to stylesheet and set styleIndex for corresponding range.
I don't know if it's worth checking out, but when working with large datasets and datatables in the past I usually use ClosedXML to get it done. It's easy to just pass a datatable and let it handle creating the XLSX for it. I have it running my my Windows Server 2008 r2 without issue handling large requests with multiple sheets so I know it works really well.
https://closedxml.codeplex.com/

DatatGrid Itemsource using Linq i cant select any record except first

Hey im currently having problems with WPF Datagrid using linq, currently im displaying a group of records from three tables into a datagrid, this works fine and i retrieve all the relevant information correctly.
However when i load the datagrid and i click on for example the 3rd record it selects the first record and i cant change it. I can use Ctrl + click to deselect the first record.
I dont know why its doing this but ive narrowed it down to my linq query, ive tried to write a more complex linq query using joins etc, it retrieves the same data but i still have this problem :/ any ideas would be good...thank you in advance
apptGrid.ItemsSource = (from o in DbList.OrderedAppointmentList()
from s in DbList.StaffList()
from c in DbList.ClientList()
where o.Appointment_Date == apptDatePicker.SelectedDate.Value
&& o.Staff_Staff_ID == s.Staff_ID && o.Client_Client_ID == c.Client_ID
select new
{
o.Appointment_Date,
o.Appointment_Time,
o.Duration,
StaffName =
((s.Middle_Name_s_ != null) ? s.First_Name + " " + s.Middle_Name_s_ + " " + s.Last_Name : s.First_Name + " " + s.Last_Name),
ClientName =
((c.Middle_Name_s_ != null) ? c.First_Name + " " + c.Middle_Name_s_ + " " + c.Last_Name : c.First_Name + " " + c.Last_Name)
});
Try a ToList() at the end of the query.
I had something similar like you, but to me happen, that when i add rows with the same data information, the selection seems to be crazy. what i did was not give a linq query as a itemsource else put all the information into a List and next pass it to the item source.
"ive tried to write a more complex linq query using joins etc,"
That's never going to help.
Write a program that is human readable (and not just computer readable). And I can bet, you will find the problem and the solution in that iteration.

Categories

Resources