Set table style. C# - closed xml - c#

I am looking for a way to apply a table style to the inserted data in an excel file.
I use the library closed xml
How can I do it?
Sample table I want to get
using (XLWorkbook wb = new XLWorkbook(excel))
{ IXLWorksheet ws = wb.Worksheets.Last();
string Qry;
using (SqlCommand cmd = new SqlCommand(Qry, sqlConn))
{
sqlConn.Open();
using (SqlDataReader dr = cmd.ExecuteReader())
{
System.Data.DataTable schemaTable = dr.GetSchemaTable();
int i = 1;
foreach (DataRow rowt in schemaTable.Rows)
{
while (dr.Read())
{
row++;
for (int j = 0; j < dr.FieldCount; j++)
{
if (!dr.IsDBNull(j))
{
switch (dr.GetDataTypeName(j))
{
case "Varchar2":
string s = dr.GetString(j);
if (s.Substring(0, 1) == "=")
s = " " + s;
ws.Cell(row, j + 1).Value = s;
break;
case "nvarchar":
ws.Cell(row, j + 1).Value = dr.GetString(j);
break;
default:
break;
}}}}}}}

Based on the ClosedXML documentation:
// create the Excel workbook
var wb = new XLWorkbook();
// creates the worksheet
var ws = wb.AddWorksheet("Sheet1");
// the range for which you want to add a table style
var range = ws.Range(1, 1, 5, 5);
// create the actual table
var table = range.CreateTable();
// apply style
namesTable.Theme = XLTableTheme.TableStyleLight12;

Related

Connect Empty Points in Word Chart

I'm creating a Chart in my C# Application with Word Interop. Inside this graph i have some empty data points. How can i connect the empty points programmatically? I'd like to achieve this but inside code. Can anybode help me? Thank you
Edit:
Here is the Code
Dictionary<DateTime, Dictionary<string, decimal>> visuData = new Dictionary<DateTime, Dictionary<string, decimal>>();
string startTime = null;
string endTime = null; //Variablen für die Zeitspanne, aus der Versuchsdaten abgerufen werden sollen
query = "SELECT MIN(Starttime) AS Starttime, MAX(Starttime) AS Endtime FROM dbo.Table WHERE ID = " + checkBox.Text;
con = new SqlConnection(mtecConnectionString);
cmd = new SqlCommand(query, con);
con.Open();
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
startTime = reader.GetDateTime(0).ToString("yyyy-MM-dd hh:mm:ss.fff");
endTime = reader.GetDateTime(1).ToString("yyyy-MM-dd hh:mm:ss.fff");
}
con.Close(); //Zeitspanne bestimmen
if (startTime == null || endTime == null)
return; //Falls keine Daten vorliegen, wird die Methode beendet
List<string> variables = new List<string>();
query = "SELECT ...";
con = new SqlConnection(#"...");
cmd = new SqlCommand(query, con); //Abfrage für Versuchsdaten und Verbindung zur Datenbank setzen
con.Open();
reader = cmd.ExecuteReader();
while (reader.Read())
{
if (visuData.ContainsKey(reader.GetDateTime(2)))
{
visuData[reader.GetDateTime(2)].Add(reader.GetString(0),
reader.GetDecimal(1));
}
else
{
visuData.Add(reader.GetDateTime(2), new Dictionary<string, decimal>());
visuData[reader.GetDateTime(2)].Add(reader.GetString(0),
reader.GetDecimal(1));
}
if (!variables.Contains(reader.GetString(0)))
variables.Add(reader.GetString(0));
}
con.Close();
Chart chart = document.InlineShapes.AddChart2(-1, XlChartType.xlLineMarkers, paragraph.Range).Chart;
Microsoft.Office.Interop.Excel.Workbook excelWorkbook = chart.ChartData.Workbook;
excelWorkbook.Application.WindowState = Microsoft.Office.Interop.Excel.XlWindowState.xlMinimized;
Microsoft.Office.Interop.Excel.Worksheet excelWorksheet = excelWorkbook.Worksheets[1];
for(int j = 2; j < variables.Count + 2; j++)
{
excelWorksheet.Cells[1, j].Value = variables[j - 2];
}
int rowIndex = 2;
foreach (DateTime moment in visuData.Keys)
{
excelWorksheet.Cells[rowIndex, 1].Value = moment.ToString("HH:mm:ss");
for(int j = 2; j < variables.Count + 2; j++)
{
if (visuData[moment].ContainsKey(variables[j - 2]))
excelWorksheet.Cells[rowIndex, j].Value = visuData[moment][variables[j - 2]];
}
rowIndex += 1;
}
chart.ChartTitle.Text = "Batch ID " + checkBox.Text;
chart.Refresh();
excelWorkbook.Close(Type.Missing, Type.Missing, Type.Missing);
I want to display a few variables over time. So I created a dict with the timestamp as key and another dict as value. Inside this second dict I'm using the key to identify the variable and the value to get the value.
This looks like:
2021-12-02 08:00:00 --> Var 1 : 1
2021-12-02 08:00:00 --> Var 2 : 2
2021-12-02 08:05:00 --> Var 1 : 3
2021-12-02 08:05:00 --> Var 3 : 4
The actual Output is, that I have a chart in the created word document. For Var 3 is the value 0 at 8am displayed but I dont want any value for var 3 at 8 am. Same thing with Var 2...
I hope its more clear now
I found the solution myself.
I added before refreshing the chart folling line:
chart.DisplayBlanksAs = Microsoft.Office.Interop.Word.XlDisplayBlanksAs.xlInterpolated;

Saving data from SQL query in excel in C# console app

I have a c# program.cs code which is created to save results from sql query to xls file, the problem is that I have two sql query and there are two result sets which need to written to the excel file, I am able to write the 1st result through the below code but not able to write the second result, can you please help on this? Please see my code below, I am using same code block for both the queries but always seem to get results from 1st query.
static void Main(string[] args)
{
//SqlConnection cnn;
//string connectionstring = null;
string connectionstring = "Integrated Security = SSPI;Initial Catalog=Database; Data Source=<Instance Name>;";
string sql1 = null;
string sql2 = null;
string data = null;
string data1 = null;
int i = 0;
int j = 0;
string Filename = #"E:\file\testfile.xls";
if (!File.Exists(Filename))
{
File.Create(Filename).Dispose();
using (TextWriter tw = new StreamWriter(Filename))
{
tw.WriteLine("The very first line!");
tw.Close();
}
}
////*** Preparing excel Application
Excel.Application xlApp;
Excel.Workbook xlWorkBook;
Excel.Worksheet xlWorkSheet;
object misValue = System.Reflection.Missing.Value;
///*** Opening Excel application
xlApp = new Microsoft.Office.Interop.Excel.Application();
xlWorkBook = xlApp.Workbooks.Open(Filename);
xlWorkSheet = (Excel.Worksheet)(xlWorkBook.ActiveSheet as Excel.Worksheet);
xlApp.DisplayAlerts = false;
SqlConnection conn = new SqlConnection(connectionstring);
//cnn = new SqlConnection(connectionstring);
conn.Open();
////** Write your Sql Query here
sql1 = "Select top 5 DocumentId, DocFileName from <table> order by CreateDate desc";
sql2 = "Select top 5 DocID, Title from <Table> order by CreateDate desc";
///*** Preparing to retrieve value from the database
SQL.DataTable dtable = new SQL.DataTable();
SqlDataAdapter dscmd = new SqlDataAdapter(sql1, conn);
SQL.DataSet ds = new SQL.DataSet();
dscmd.Fill(dtable);
////*** Generating the column Names here
string[] colNames = new string[dtable.Columns.Count];
int col = 0;
foreach (SQL.DataColumn dc in dtable.Columns)
colNames[col++] = dc.ColumnName;
char lastColumn = (char)(65 + dtable.Columns.Count - 1);
xlWorkSheet.get_Range("A1", lastColumn + "1").Value2 = colNames;
xlWorkSheet.get_Range("A1", lastColumn + "1").Font.Bold = true;
xlWorkSheet.get_Range("A1", lastColumn + "1").VerticalAlignment
= Excel.XlVAlign.xlVAlignCenter;
/////*** Inserting the Column and Values into Excel file
for (i = 0; i <= dtable.Rows.Count - 1; i++)
{
for (j = 0; j <= dtable.Columns.Count - 1; j++)
{
data = dtable.Rows[i].ItemArray[j].ToString();
xlWorkSheet.Cells[i + 2, j + 1] = data;
xlWorkBook.Save();
}
}
//Enter new block in Excel -- for the second query, I need help here below
SQL.DataTable dtable1 = new SQL.DataTable();
SqlDataAdapter dscmd1 = new SqlDataAdapter(sql2, conn);
SQL.DataSet ds1 = new SQL.DataSet();
dscmd1.Fill(dtable1);
////*** Generating the column Names here
string[] colNames1 = new string[dtable1.Columns.Count];
int col1 = 0;
foreach (SQL.DataColumn dc in dtable1.Columns)
colNames1[col1++] = dc.ColumnName;
char lastColumn1 = (char)(68 + dtable1.Columns.Count - 1);
xlWorkSheet.get_Range("D1", lastColumn1 + "1").Value2 = colNames1;
xlWorkSheet.get_Range("D1", lastColumn1 + "1").Font.Bold = true;
xlWorkSheet.get_Range("D1", lastColumn1 + "1").VerticalAlignment
= Excel.XlVAlign.xlVAlignCenter;
/////*** Inserting the Column and Values into Excel file
for (i = 0; i <= dtable1.Rows.Count - 1; i++)
{
for (j = 0; j <= dtable1.Columns.Count - 1; j++)
{
data1 = dtable1.Rows[i].ItemArray[j].ToString();
xlWorkSheet.Cells[i + 2, j + 1] = data1;
xlWorkBook.Save();
}
}
//end of block
xlWorkBook.Close(true, misValue, misValue);
xlApp.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlWorkSheet);
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlWorkBook);
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp);
}
Image from Excel result

OleDbDataReader skips first record

I have the following code :
OleDbDataReader xlsReader =
new OleDbCommand("Select * from [" +spreadSheetName + "]", xlsFileConnection).
ExecuteReader();
In the spreadSheetName parameter i keep my file name.
The connection string for xlsFileConnection was set as
"Provider=Microsoft.Jet.OLEDB.4.0;
Data Source='<directory path>';
Extended Properties='text; HDR=No; FMT=Delimited'"
When i start to execute while (xlsReader.Read()) i take a row #2 but not #1 from data source.
The first suggestion was that HDR parameter has invalid value but it seems it's ok.
There are better and easier ways to reading xlsx files, if I were you I would grab closedXML from nuget and this code to read your excel file into a data table
public void ProcessExcel(string fileName)
{
_dt = ImportSheet(fileName);
dgContacts.ItemsSource = _dt.DefaultView;
}
public static DataTable ImportSheet(string fileName)
{
var datatable = new DataTable();
var workbook = new XLWorkbook(fileName);
var xlWorksheet = workbook.Worksheet(1);
var range = xlWorksheet.Range(xlWorksheet.FirstCellUsed(), xlWorksheet.LastCellUsed());
var col = range.ColumnCount();
var row = range.RowCount();
datatable.Clear();
for (var i = 1; i <= col; i++)
{
var column = xlWorksheet.Cell(1, i);
datatable.Columns.Add(column.Value.ToString());
}
var firstHeadRow = 0;
foreach (var item in range.Rows())
{
if (firstHeadRow != 0)
{
var array = new object[col];
for (var y = 1; y <= col; y++)
{
array[y - 1] = item.Cell(y).Value;
}
datatable.Rows.Add(array);
}
firstHeadRow++;
}
return datatable;
}
The grab the data out of your datatable as you need.
This is live and working code, so you just need to copy and paste

How to close ExcelPackage using EPPlus in C#?

I'm using epplus to write in a file an extense quantity of information in an excel template, but then I need to close the ExcelPackage as to be usable with the Excel application. It throws me this exception: "System.Runtime.InteropServices.COMException (0x800A03EC): Exception from HRESULT: 0x800A03EC"
private void FillCardsSheet()
{
xlPackage = new ExcelPackage(Template);
wsCards = xlPackage.Workbook.Worksheets[4];
string command = "SELECT * FROM dbo_serial_cards WHERE type <> 'EXT' AND LEFT([device_tag], 2) <> '!!'";
OleDbCommand cmd = new OleDbCommand(command, CON);
OleDbDataReader reader = cmd.ExecuteReader();
int row = 1;
while (reader.Read())
{
row++;
for (int col = 1; col <= 16; col++)
{
wsCards.Cells[row, col].Value = reader.GetValue(col - 1);
}
}
xlPackage.SaveAs(Template);
xlPackage.Dispose();
}
Hard to say without more details about your connection and objects. What is 'Template'? Might help if you say which line is generating the error (like #mason mentioned). That is a COM error you seem to be getting so it could be with the db connection or maybe the package itself. Since the package is being managed outside the method make sure it is not locked or closed.
This worked fine for me connection to a local SQL Server db:
[TestMethod]
public void SQL_Reader_Test()
{
var Template = new FileInfo(#"c:\temp\temp.xlsx");
if (Template.Exists)
Template.Delete();
var xlPackage = new ExcelPackage(Template);
//var wsCards = xlPackage.Workbook.Worksheets[4];
var wsCards = xlPackage.Workbook.Worksheets.Add("Cards");
//const string constring = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\temp\northwind.mdb;Persist Security Info=False;";
const string constring = #"Provider=SQLNCLI11;Data Source=MYMACHINENAME\SQLEXPRESS;Initial Catalog=AdventureWorks;UID=AdventureWorks; Pwd=AdventureWorks";
using (var CON = new OleDbConnection(constring))
{
CON.Open();
//string command = "SELECT * FROM dbo_serial_cards WHERE type <> 'EXT' AND LEFT([device_tag], 2) <> '!!'";
const string command = "SELECT * FROM Person.Address";
var cmd = new OleDbCommand(command, CON);
var reader = cmd.ExecuteReader();
int row = 1;
while (reader.Read())
{
row++;
//for (int col = 1; col <= 16; col++)
for (int col = 1; col <= reader.FieldCount; col++)
{
wsCards.Cells[row, col].Value = reader.GetValue(col - 1);
}
}
xlPackage.SaveAs(Template);
xlPackage.Dispose();
}
}
Try to use the ExcelPackage within an Using-Block:
using (ExcelPackage xlsPackage = new ExcelPackage(Template))
{
// Your Code
xlPackage.SaveAs(Template);
}

How to convert datatype before Importing Excel file to Sql database

Here I have this Import from excel file to sql database class. It was working correctly till now but as my excel file cells are all strings type , So when Importing , the datatype does not match as sql database. How to convert it to their respective datatype before importing?
public static void ImportToSql(string excelfilepath)
{
string myexceldataquery = "select LocalSKU,ItemName, QOH,Price,Discontinued,Barcode,Integer2,Integer3,SalePrice,SaleOn,Price2 from [sheet1$]";
try
{
string sexcelconnectionstring = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source =" + excelfilepath + "; Extended Properties=\"Excel 12.0; HDR=Yes; IMEX=2\"";
string ssqlconnectionstring = "Data Source=DELL\\SQLSERVER1;Trusted_Connection=True;DATABASE=Test;CONNECTION RESET=FALSE";
SqlConnection sqlconn = new SqlConnection(ssqlconnectionstring);
//series of commands to bulk copy data from the excel file into our sql table
OleDbConnection oledbconn = new OleDbConnection(sexcelconnectionstring);
OleDbCommand oledbcmd = new OleDbCommand(myexceldataquery, oledbconn);
oledbconn.Open();
OleDbDataReader dr = oledbcmd.ExecuteReader();
SqlCommand sqlcmd = new SqlCommand(#"MERGE Inventory AS target
USING (select LocalSKU,ItemName, QOH,Price,Discontinued,Barcode,Integer2,Integer3,SalePrice,SaleOn,Price2 from #source) as source
ON (source.LocalSKU = target.LocalSKU)
WHEN MATCHED THEN
UPDATE SET ItemName=source.ItemName,Price=source.Price,Discontinued=source.Discontinued,Barcode=source.Barcode,Integer2=source.Integer2,Integer3 = source.QOH,SalePrice=source.SalePrice,SaleOn=source.SaleOn,Price2=source.Price2;", sqlconn);
SqlParameter param;
param = sqlcmd.Parameters.AddWithValue("#source",dr);
param.SqlDbType = SqlDbType.Structured;
param.TypeName = "dbo.InventoryType";
sqlconn.Open();
sqlcmd.ExecuteNonQuery();
sqlconn.Close();
while (dr.Read())
{
}
oledbconn.Close();
Console.WriteLine(".xlsx file imported succssessfully into database.");
}
The easiest thing to do would be to convert them in your SQL statement by using CAST:
SqlCommand sqlcmd = new SqlCommand(
#"MERGE Inventory AS target
USING (select LocalSKU, ItemName, QOH = CAST(QOH AS int)
, Price = CAST(Price AS decimal(10,2)), Discontinued = CAST(Discontinued AS bit)
, Barcode, Integer2 = CAST(Integer2 AS int)
, Integer3 = CAST(Integer3 AS int), SalePrice = CAST(SalePrice AS decimal(10,2))
, SaleOn, Price2 = CAST(Price2 AS decimal(10,2)) from #source) as source
ON (source.LocalSKU = target.LocalSKU)
WHEN MATCHED THEN
UPDATE (. . . )
I'm guessing on some of the conversions, but you get the idea. You'll need to make sure that the data in the spreadsheet all match the datatypes you want to convert them to, as one mistake will cause the whole statement to fail. Something more robust will take a lot more code.
First browse the excel file and put data in datagrid and then read datagrid row one by one.
i give you 2 function for that. one is browse the excel file and put data in datagrid and second one is read datagrid and put record in database
Excel Export Function
private void export_btn_Click(object sender, EventArgs e)
{
Microsoft.Office.Interop.Excel.Application ExcelApp =
new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel._Workbook ExcelBook;
Microsoft.Office.Interop.Excel._Worksheet ExcelSheet;
int i = 0;
int j = 0;
//create object of excel
ExcelBook = (Microsoft.Office.Interop.Excel._Workbook)ExcelApp.Workbooks.Add(1);
ExcelSheet = (Microsoft.Office.Interop.Excel._Worksheet)ExcelBook.ActiveSheet;
//export header
for (i = 1; i <= this.dataGridView1.Columns.Count; i++)
{
ExcelSheet.Cells[1, i] = this.dataGridView1.Columns[i - 1].HeaderText;
}
//export data
for (i = 1; i <= this.dataGridView1.RowCount; i++)
{
for (j = 1; j <= dataGridView1.Columns.Count; j++)
{
ExcelSheet.Cells[i + 1, j] = dataGridView1.Rows[i - 1].Cells[j - 1].Value;
}
}
ExcelApp.Visible = true;
//set font Khmer OS System to data range
Microsoft.Office.Interop.Excel.Range myRange = ExcelSheet.get_Range(
ExcelSheet.Cells[1, 1],
ExcelSheet.Cells[this.dataGridView1.RowCount + 1,
this.dataGridView1.Columns.Count]);
Microsoft.Office.Interop.Excel.Font x = myRange.Font;
x.Name = "Arial";
x.Size = 10;
//set bold font to column header
myRange = ExcelSheet.get_Range(ExcelSheet.Cells[1, 1],
ExcelSheet.Cells[1, this.dataGridView1.Columns.Count]);
x = myRange.Font;
x.Bold = true;
//autofit all columns
myRange.EntireColumn.AutoFit();
ExcelApp.ActiveWorkbook.SaveCopyAs("E:\\reports.xlsx");
ExcelApp.ActiveWorkbook.Saved = true;
ExcelApp.Quit();
MessageBox.Show("Excel file created,you can find the file E:\\reports.xlsx");
//
ExcelSheet = null;
ExcelBook = null;
ExcelApp = null;
}
Read Datagrid
public void readDataGrid()
{
for (int i = 0; i < dataGridView1.Rows.Count; i++)
{
try
{
//Here read one by one cell and convert it into your required datatype and store it in
String rowcell1 = dataGridView1.Rows[i].Cells[0].Value.ToString();
}
catch (Exception err)
{
}
count++;
}
}
I this is help you.

Categories