I have a table in Excel
col1 col2
2 4
1 5
5 3
8 7
I need to compare 2 columns, col1 & col2. If the values from column col2>col1 then fill in the cell in the column col2 in red color. If the values from column col2
I wrote an example method, but I do not know how to fix it further.
private static void BackroundColor(string filePathNameExcel)
{
int i = 1;
using (XLWorkbook wb = new XLWorkbook(filePathNameExcel))
{
IXLWorksheet ws = wb.Worksheet("sheetMy");
int col = 1;
for (int j = 1; j <= col; j++)
{
if (j == 3)
{
for (int irow = 1; irow <= i; irow++)
{
if (ws.Cell(irow, 3).GetString() == "2")
{
string dat = ws.Cell(irow, 3).GetString();
ws.Cell(irow, 1).Style.Fill.BackgroundColor = XLColor.Red;
}
}
}
}
wb.SaveAs(filePathNameExcel, true);
}
}
I'm not able to fully understand your codes logic without seeing more of your data format so I made a few assumptions and simplified it for this example.
Starting Data
Code
private static void BackroundColor(string filePathNameExcel)
{
using (XLWorkbook wb = new XLWorkbook(filePathNameExcel))
{
IXLWorksheet ws = wb.Worksheet("sheetMy");
int lastRow = ws.LastRowUsed().RowNumber();
// Loop each row
for (int irow = 1; irow <= lastRow; irow++)
{
// Check if column 1 row value is less then column 2 row value
if ((double)ws.Cell(irow, 1).Value < (double)ws.Cell(irow,2).Value)
{
ws.Cell(irow, 2).Style.Fill.BackgroundColor = XLColor.Red;
}
}
wb.SaveAs(filePathNameExcel, true);
}
}
Result
Related
I want to extract some data in the datatable, and want to send the email.
But when I extract the data, excel has many blanks between the extracted data.
The data which is not extracted make a blank row.
When I try to use RemoveRow() function, it doesn't work and still has a blank row.
private void Email()
{
//get the data from database
DataTable data = GetData();
int maxLavel = Convert.ToInt32(data.Compute("max([AssignedID])", string.Empty));
IWorkbook workbook;
workbook = new HSSFWorkbook();
for (int Emp = 0; Emp < maxLavel; Emp++)
{
ISheet sheet1 = workbook.CreateSheet("Sheet 1");
int num = 0;
//make a header row
IRow row1 = sheet1.CreateRow(0);
for (int j = 0; j < data.Columns.Count; j++)
{
ICell cell = row1.CreateCell(j);
String columnName = data.Columns[j].ToString();
cell.SetCellValue(columnName);
}
//loops through data
for (int i = 0; i < data.Rows.Count; i++)
{
IRow row = sheet1.CreateRow(i + 1);
if (Emp == Convert.ToInt32(data.Rows[i][0]))
{
num++;
ICell cell = row.CreateCell(j);
for (int j = 0; j < data.Columns.Count; j++)
{
sheet1.AutoSizeColumn(j); //control cell width
String columnName = data.Columns[j].ToString();
cell.SetCellValue(data.Rows[i][columnName].ToString());
}
}
else ///here has problems
{
var row = sheet1.GetRow(i);
//sheet1.RemoveRow(row);
sheet1.ShiftRows(i + 1, sheet1.LastRowNum + 1, -1);
}
}
if (num != 0)
{
//send email
}
}
}
I'm not sure why you need to resend the same file again with different contents instead of simply sending a different file, but could you perhaps try moving the creation of your sheet inside the for loop, and try removing the entire sheet instead? E.g. something like this:
private void Email()
{
//get the data from database
DataTable data = GetData();
int maxLavel = Convert.ToInt32(data.Compute("max([AssignedID])", string.Empty));
IWorkbook workbook;
workbook = new HSSFWorkbook();
for (int Emp = 0; Emp < maxLavel; Emp++)
{
ISheet sheet1 = workbook.CreateSheet("Sheet 1");
int num = 0;
//make a header row
IRow row1 = sheet1.CreateRow(0);
for (int j = 0; j < data.Columns.Count; j++)
{
ICell cell = row1.CreateCell(j);
String columnName = data.Columns[j].ToString();
cell.SetCellValue(columnName);
}
//loops through data
for (int i = 0; i < data.Rows.Count; i++)
{
IRow row = sheet1.CreateRow(i + 1);
if (Emp == Convert.ToInt32(data.Rows[i][0]))
{
num++;
for (int j = 0; j < data.Columns.Count; j++)
{
ICell cell = row.CreateCell(j);
sheet1.AutoSizeColumn(j); //control cell width
String columnName = data.Columns[j].ToString();
cell.SetCellValue(data.Rows[i][columnName].ToString());
}
}
}
if (num != 0)
{
//send email
}
workbook.remove(sheet1);
}
}
I figure it out..I don't need to remove the row.
IRow row = sheet1.CreateRow(i);
This should be changed.
for (int i = 0; i < data.Rows.Count; i++)
{
if (Emp == Convert.ToInt32(data.Rows[i][0]))
{
IRow row = sheet1.CreateRow(row_num);
num++; row_num++;
for (int j = 0; j < data.Columns.Count; j++)
{
ICell cell = row.CreateCell(j);
sheet1.AutoSizeColumn(j); //control cell width
String columnName = data.Columns[j].ToString();
cell.SetCellValue(data.Rows[i][columnName].ToString());
}
}
}
I'm using itextSharp to export a DataTable to a pdf table. I can export the data to a pdf table using the sample code i have posted below. The DataTable contains close to 21 columns.
The first column in the pdf (DataTable) might contain similar values for any number of rows. If the data values in first column for a group of rows is similar, i want to merge the first 3 columns of those rows as one cell.
I'm having trouble modifying the code below to achieve this.
public iTextSharp.text.Table GetItextTable(DataTable dtChartData, string reportType)
{
int intCols = dtChartData.Columns.Count; //Total number of columns
int intRows = dtChartData.Rows.Count; //Total number of rows
iTextSharp.text.Table pdfTable = new iTextSharp.text.Table(intCols, intRows);
try
{
pdfTable.BorderWidth = 1;
pdfTable.Width = 100;
pdfTable.Padding = 1;
pdfTable.Spacing = 1;
/*creating table headers */
for (int i = 0; i < intCols; i++)
{
iTextSharp.text.Cell cellCols = new iTextSharp.text.Cell();
iTextSharp.text.Font ColFont = iTextSharp.text.FontFactory.GetFont("Tahoma", 07,
iTextSharp.text.Font.BOLD);
for (int l = 0; l < dtChartData.Columns.Count; l++)
{
if (dtChartData.Columns[l].ColumnName.Contains("_"))
{
dtChartData.Columns[l].ColumnName = dtChartData.Columns[l].ColumnName.Replace("_", " ");
}
}
iTextSharp.text.Chunk chunkCols = new iTextSharp.text.Chunk(dtChartData.Columns[i].ColumnName,ColFont);
cellCols.HorizontalAlignment = iTextSharp.text.Element.ALIGN_CENTER;
if ((chunkCols.ToString().ToLower() == "ReportDetails"))
{
cellCols.HorizontalAlignment = iTextSharp.text.Element.ALIGN_CENTER;
}
}
/* loop that take values from every row in datatable and insert in itextsharp table */
for (int k = 0; k < intRows; k++)
{
for (int j = 0; j < intCols; j++)
{
iTextSharp.text.Cell cellRows = new iTextSharp.text.Cell();
iTextSharp.text.Font RowFont = iTextSharp.text.FontFactory.GetFont("Tahoma", 07);
iTextSharp.text.Chunk chunkRows = new iTextSharp.text.Chunk(dtChartData.Rows[k][j].ToString(),RowFont);
cellRows.HorizontalAlignment = iTextSharp.text.Element.ALIGN_CENTER;
cellRows.Add(chunkRows);
pdfTable.AddCell(cellRows);
}
}
}
catch (Exception ex)
{
//error handling code here removed
}
return pdfTable;
}
Have you tried to change the Colspan?
iTextSharp.text.Cell cell = new iTextSharp.text.Cell();
cell.AddElement(new Paragraph("colspan 3"));
cell.Colspan = 3;
table.AddCell(cell);
In this case, cell will span three columns.
try this. i just edited your code, not checked
here i have edited 1 line of your code and added a new line (total 2 lines of change only).
dont forget to combine headding row like this, if you need
/* loop that take values from every row in datatable and insert in itextsharp table */
for (int k = 0; k < intRows; k++)
{
for (int j = 2; j < intCols; j++)// EDIT: if all first 3 cols are same, then starts with 2
{
iTextSharp.text.Cell cellRows = new iTextSharp.text.Cell();
if(j == 2) cellRows.Colspan = 3;// ADD: it'll gives a 3 times long cell
iTextSharp.text.Font RowFont = iTextSharp.text.FontFactory.GetFont("Tahoma", 07);
iTextSharp.text.Chunk chunkRows = new iTextSharp.text.Chunk(dtChartData.Rows[k][j].ToString(),RowFont);
cellRows.HorizontalAlignment = iTextSharp.text.Element.ALIGN_CENTER;
cellRows.Add(chunkRows);
pdfTable.AddCell(cellRows);
}
}
The problem is that I need to insert data into Excel from the collection several times using a single template for the entire collection.
using (var pckg = new ExcelPackage(new FileInfo(association.TemplatePath)))
{
var workSheet = pckg.Workbook.Worksheets[1];
var dataTable = WorksheetToDataTable(workSheet);
/*Some stuff*/
FindAndReplaceValue(workSheet, dictionary, row);
}
private DataTable WorksheetToDataTable(ExcelWorksheet oSheet)
{
int totalRows = oSheet.Dimension.End.Row;
int totalCols = oSheet.Dimension.End.Column;
DataTable dt = new DataTable(oSheet.Name);
DataRow dr = null;
for (int i = 1; i <= totalRows; i++)
{
if (i > 1) dr = dt.Rows.Add();
for (int j = 1; j <= totalCols; j++)
{
if (i == 1)
dt.Columns.Add((oSheet.Cells[i, j].Value ?? "").ToString());
else
dr[j - 1] = (oSheet.Cells[i, j].Value ?? "").ToString();
}
}
return dt;
}
First picture - My template. Second - First element of collection (with data, style, merging). Third - Other elements has only data
I just made copies of rows
for (int i = 0; i < invoiceList.Count; i++)
{
workSheet.Cells[1, 1, totalRows, totalCols].Copy(workSheet.Cells[i * totalRows + 1, 1]);
}
If you want to copy range just use :
workSheet.Cells["A1:I1"].Copy(workSheet.Cells["A4:I4"]);
I have an Excel file with 2 columns [file in my pc]? Now iam getting 2 columns with 8 rows with below code.but continuously i should get 5*2=10 more of same columns with 8 rows in datagridview.
I have written the code which gives result only 2 columns but I should get 10 more columns with 8 rows.below is my code
for (int Cnum = 1; Cnum <= ShtRange.Columns.Count; Cnum++)
{
dt.Columns.Add((ShtRange.Cells[1, Cnum] as Excel.Range).Value2.ToString());
}
for (int Rnum = 2; Rnum <= 9; Rnum++)
{
dt.Rows.Add((ShtRange.Cells[Rnum, 1] as Excel.Range).Value2.ToString(),
(ShtRange.Cells[Rnum, 1] as Excel.Range).Value2.ToString());
}
}
for (int i = 0; i < 13; i++)
{
DataGridViewTextBoxCell txtbx = new DataGridViewTextBoxCell();
DataGridViewColumn txcol = new DataGridViewColumn();
txcol.CellTemplate = txtbx;
txcol.HeaderText = "column" + i.ToString();
dg1.Columns.Add(txcol);
}
dg1.Rows.Add(8);
int dgRw, dgCol;
dgRw = dgCol = 0;
foreach (DataRow dr in dt.Rows)
{
dg1[dgCol, dgRw].Value = dr[0].ToString();
dgRw++;
if (dgRw == 8)
{
dgCol++;
dgRw = 0;
}
I need to display data that will be hybrid "hard-coded" strings and data from a database. Specifically, every even-numbered column contains string values that are NOT from the database, and every odd-numbered column contains data. So column 1, for example, will contain values 1 through 12 from the database, so that the first two columns look something like this (and the same pattern repeats several times):
00:00 BoundVal1
00:15 BoundVal2
. . .
02:45 BoundVal12
Is this possible?
Right now I'm using a TableLayoutPanel for this, but the coding for that is a little pretzly (not a Steely Dan reference).
You could just build a DataTable object and set it as DataGridView's DataSource.
I finally got this working, based on code from Mohamed Mansour at http://social.msdn.microsoft.com/forums/en-US/csharpgeneral/thread/ca89a857-6e17-44a7-8cdb-90d64a0a7bbe
int RowCount = 12;
Dictionary<int, string> PlatypusPairs;
. . .
private void button3_Click(object sender, EventArgs e) {
// Retrieve data as dictionary
PlatypusPairs = InterpSchedData.GetAvailableForPlatypusAndDate(oracleConnectionTestForm, 42, DateTime.Today.Date);
int ColumnCount = 16;
// Add the needed columns
for (int i = 0; i < ColumnCount; i++) {
string colName = string.Format("Column{0}", i + 1);
dataGridView1.Columns.Add(colName, colName);
}
for (int row = 0; row < RowCount; row++) {
// Save each row as an array
string[] currentRowContents = new string[ColumnCount];
// Add each column to the currentColumn
for (int col = 0; col < ColumnCount; col++) {
currentRowContents[col] = GetValForCell(row, col);
}
// Add the row to the DGV
dataGridView1.Rows.Add(currentRowContents);
}
}
private string GetValForCell(int Row, int Col) {
string retVal;
if (Col % 2 == 0) {
retVal = GetTimeStringForCell(Row, Col);
} else {
retVal = GetPlatypusStringForCell(Row, Col);
}
return retVal;
}
private string GetTimeStringForCell(int Row, int Col) {
const int TIME_INCREMENT_STEP = 15;
var dt = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 0, 0, 0);
dt = dt.AddMinutes(((Col * (RowCount / 2)) + Row) * TIME_INCREMENT_STEP);
return dt.ToString("HH:mm");
}
private string GetPlatypusStringForCell(int Row, int Col) {
int multiplicand = Col / 2;
string val = string.Empty;
int ValToSearchFor = (multiplicand * RowCount) + (Row + 1);
if (PlatypusPairs.ContainsKey(ValToSearchFor)) {
PlatypusPairs.TryGetValue(ValToSearchFor, out val);
if (val.Equals(0)) {
val = string.Empty;
}
}
return val;
}