I want to change the structure of my DataTable. My datatable shows data in following format:-
I pivoted my datatable, using following code.
public DataTable PivotTable(DataTable source)
{
DataTable dest = new DataTable("Pivoted" + source.TableName);
dest.Columns.Add(" ");
foreach (DataRow r in source.Rows)
dest.Columns.Add(r[0].ToString());
for (int i = 0; i < source.Columns.Count - 1; i++)
{
dest.Rows.Add(dest.NewRow());
}
for (int r = 0; r < dest.Rows.Count; r++)
{
for (int c = 0; c < dest.Columns.Count; c++)
{
if (c == 0)
dest.Rows[r][0] = source.Columns[r + 1].ColumnName;
else
dest.Rows[r][c] = source.Rows[c - 1][r + 1];
}
}
dest.AcceptChanges();
return dest;
}
After pivoting my Datatable shows record in following format:-
But I need result in following format:-
That is if there are 1 Sector it should show till 1 stop, if there are 3 Sector then it should show till 3 stop. It should increase or decrease automatically.
Please help me with the code.
Thanks
Related
I have a problem when I'm trying to a loop in a DataTable that a dataset contains.
I'm doing a loop like this:
for(int i = 0; i<ds.Tables[0].Rows.Count - 1 ; i++)
The problem is that I can't get the value of the last line with this one, but if I try to get rid of the "-1" and do a loop on the whole table, I'll have an out of range exception.
This out of range exception is because I have to check if the value of a line "i" is equal to the value of a line "i+1", like this:
if (ds.Tables[0].Rows[i]["Release_No"] != ds.Tables[0].Rows[i + 1]["Release_No"])
So if I do it in a loop, when the index is on the last line it will check if the last line is equal to i+1, and it's out of the table.
So I was trying to check if the index is on the last line, then just get the value of the last line, but it seems like it doesn't work.
if(ds.Tables[0].Rows.IndexOf(ds.Tables[0].Rows[i]) == ds.Tables[0].Rows.Count)
If anyone has an idea, let me know, and of course if it is not clear enough let me know, I'll give more information and more code.
Thanks for your help and your time!
Check if it's the last record, first.
I like to refactor code to read as close to sentence form as possible, explaining what you want it to do using named variables and methods, and that often gets me unlocked.
Try to make each line of code do one thing, and one thing only, like check if it is the last row:
var data = ds.Tables[0].Rows;
var lastRow = data.Count - 1;
for(int i = 0; i < lastRow ; i++)
{
if (i == lastRow){
// This is the last row. Handle the last row here.
}
else
{
// Handle all other rows here
var currentRecord = data[i];
var nextRecord = data[i + 1];
if (currentRecord["Release_No"] != nextRecord["Release_No"])
{
// Handle unique Releases...
}
}
}
Use less than or equal to like this
for(int i = 0; i<=ds.Tables[0].Rows.Count - 1 ; i++)
I hope this may get what you want.
Something like this is better ?
var lastRow = data.Count - 1;
var data = ds.Tables[0].Rows;
for(int i = 0; i< lastRow; i++)
{
testFirstCum = Convert.ToInt32(ds.Tables[0].Rows[i]["EDI_Accum_Quantity"]);
if ( i == lastRow)
{
if (DBNull.Value.Equals(data[i]))
{
quantity = 0;
}
else
{
quantity = Convert.ToInt32(data[i]);
testFirstCum = testFirstCum + quantity;
System.Diagnostics.Debug.WriteLine(quantity);
System.Diagnostics.Debug.WriteLine(testFirstCum);
}
}
else
{
var col = ds.Tables[0].Columns;
var currentRecord = data[i];
var nextRecord = data[i + 1];
if(currentRecord["Release_No"] != nextRecord["Release_No"])
{
for (int j = col[2].Ordinal; j < col.Count; j++)
{
if (DBNull.Value.Equals(data[i][j]))
{
quantity = 0;
}
else
{
quantity = Convert.ToInt32(data[i][j]);
testFirstCum = testFirstCum + quantity;
System.Diagnostics.Debug.WriteLine(quantity);
System.Diagnostics.Debug.WriteLine(testFirstCum);
}
}
}
}
}
I have a QTableWidget with some columns and rows and want to add a filter for a particular column.
For that, I've added a QLineEdit in my Window.
I'm already able to filter the rows, when I add only one number in the QLineEdit:
for(int i=0; i<tableWidget->rowCount(); i++)
{
if(!tableWidget->item(i, column)->text().contains(lineEdit->text()))
{
tableWidget->hideRow(i);
}
}
(The slot is connected to the textEdited-Signal of the LineEdit)
What I want to do now:
When I write something like this in the QLineEdit: 10-30; Hide all rows, which doesnt have the number between 10 and 30 (>=10; <=30).
Somebody has an idea, how I can solve this?
This is my decision.
Check if lineEdit text contains two numbers.
QString test = ui->lineEdit->text();
QStringList lst = test.split('-');
if (lst.size() == 2)
Transform they in to integers.
int low = QString(lst[0]).toInt(), high = QString(lst[1]).toInt();
Now let's go to tableWidget and drop in less than or equal to these two numbers.
for (int i = 1; i <= 100; i++) {
int row = ui->tableWidget->rowCount();
ui->tableWidget->insertRow(row);
ui->tableWidget->setItem(row, 0, new QTableWidgetItem(QString::number(i)));
}
connect(ui->lineEdit, &QLineEdit::textChanged, this, [=](const QString &test) {
QStringList lst = test.split('-');
if (lst.size() == 2) {
int low = QString(lst[0]).toInt(), high = QString(lst[1]).toInt();
for (int i = 0; i < ui->tableWidget->rowCount(); i++) {
int temp = ui->tableWidget->item(i, 0)->text().toInt();
if (temp < low || temp > high) {
ui->tableWidget->hideRow(i);
} else {
ui->tableWidget->showRow(i);
}
}
}
});
In javaFx, treetableView, we can hide or show columns using "+" i.e
setTableMenuButtonVisible(true) symbol
say I have 10 columns in treetableview, but i have shown only 5, How can my program get count of only those columns which are visible (i.e 5 in this case)
U can have something like
ObservableList<TableColumn> visibleColumnList =FXCollections.observableArrayList();
ObservableList<TableColumn > tableColumnList = tableView.getColumns();
for (int j = 0; j < tableColumnList.size(); j++) {
TableColumn tableCol = tableColumnList.get(j);
if (tableCol.isVisible())
visibleColumnList.add(tableCol);
}
Long count = visibleColumnList.size();
Thanks Dev for your answer, though tableCol.isVisible method doesnt works for me, but i got it done other way round.
int count=0;
for (int j = 0; j < ltpSystemViewer.getTable().getColumnCount(); j++) {
TableColumn tableCol = ltpSystemViewer.getTable().getColumn(j);
if (tableCol.getWidth()>0)
count++;
}
return count;
I am developing a website with ASP.net (VS2015 C #).
I need to export a MySql table with a large amount of data (500000+ rows and 100 columns) to excel (xlsx), with format.
After trying many options, the NPOI (v 3.20) library allows this export using types that use streaming (SXSSFWorkbook & SXSSFSheet).
If I use XSSFWorkbook I get and Out of memory filling the rows.
With SXSSFWorkbook I have been able to format the xlsx with different fonts and colors, but I am having problems with the types of data exported:
Date types ok
Int types ok
Text ok
Decimals inputs like 100.35 --> problems, I get a text column. I need a ouput like a number 100,35.
The code I use to format the data is:
SXSSFWorkbook wb = new SXSSFWorkbook();
SXSSFSheet sh = (SXSSFSheet)wb.CreateSheet("Sheet 1");
sh.SetRandomAccessWindowSize(100);
ICellStyle testStyleHeader = wb.CreateCellStyle();
ICellStyle testStyleRow = wb.CreateCellStyle();
// Header Style
testStyleHeader.FillForegroundColor = NPOI.SS.UserModel.IndexedColors.RoyalBlue.Index;
testStyleHeader.FillPattern = FillPattern.SolidForeground;
// Double style (with 2 decimals like 453.65)
ICellStyle cellStyleDouble = wb.CreateCellStyle();
cellStyleDouble.DataFormat = wb.CreateDataFormat().GetFormat("0.00");
// Font
XSSFFont hFontBlack = (XSSFFont)wb.CreateFont();
hFontBlack.FontHeightInPoints = 11;
hFontBlack.FontName = "Calibri";
hFontBlack.Color = NPOI.SS.UserModel.IndexedColors.Black.Index;
testStyleHeader.SetFont(hFontBlack);
IRow row = sh.CreateRow(0);
int j = 0;
ICell cell = row.CreateCell(j);
// Fill Header row
cell.SetCellValue("XXXX"); cell.CellStyle = testeStyleHeader; j++; cell = row.CreateCell(j);
cell.SetCellValue("YYYY"); cell.CellStyle = testeStyleHeader; j++; cell = row.CreateCell(j);
cell.SetCellValue("ZZZZ"); cell.CellStyle = testeStyleHeader; j++; cell = row.CreateCell(j);
cell.SetCellValue("WWWW"); cell.CellStyle = testeStyleHeader; j++; cell = row.CreateCell(j);
// Fill Rows
int i = 1; // row Number
IRow row2; // No Header Row
ICell cell2; // No Header cell
while (dr.Read()) // dr is the DataReader
{
row2 = sh.CreateRow(i);
for (int cont = 0; cont < NumColumns; cont++)
{
if (cont == 0) // This column is a date
{
…. // code for date format
}
else if (cont == 3) // Double column with 2 decimals¡! (values samples 100.45 5654.80 etc.)
{
ICell cell3 = row2.CreateCell(j, NPOI.SS.UserModel.CellType.Numeric);
cell3.CellStyle = cellStyleDouble;
cell3.SetCellValue(Convert.ToDouble(dr[cont]));
}
else
{…. // code for tex format, int format etc.
}
}
i++;
}
With this code, in the decimal column (cont ==3), I get a text column.
However, with the same code, if I declare the no streaming types:
XSSFWorkbook wb = new XSSFWorkbook();
XSSFSheet sh = (SSFSheet)wb.CreateSheet("Sheet 1");
Only with this changes I get a perfect numeric columnn 3...
For this line:
cellStyleDouble.DataFormat = wb.CreateDataFormat().GetFormat("0.00");
I have tried with different types:
"#.#"
"#,##0.000"
"##.#"
Etc…
In some cases I get a number, but not with the desired format.
So...streaming types do not allow this formatting?
Just change the Culture Info to en-US
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-Us");
ISheet worksheet = Workbook.CreateSheet(dt.TableName);
IRow HeaderRow = worksheet.CreateRow(0);
for (int i = 0; i < dt.Columns.Count; i++)
{
ICell HeaderCell = HeaderRow.CreateCell(i);
HeaderCell.SetCellValue(dt.Columns[i].ColumnName);
}
for (int j = 0; j < dt.Rows.Count; j++)
{
IRow Row = worksheet.CreateRow(j + 1);
for (int i = 0; i < dt.Columns.Count; i++)
{
ICell Cell = Row.CreateCell(i);
if (dt.Columns[i].DataType.IsOfType(typeof(decimal)) && dt.Rows[j][i] != DBNull.Value)
{
Cell.SetCellType(CellType.Numeric);
Cell.SetCellValue((double)dt.Rows[j][i]);
}
else
Cell.SetCellValue(dt.Rows[j][i].ToString());
}
}
Thread.CurrentThread.CurrentCulture = new CultureInfo("pt-Br");
It works for me!
can you try your formatting based on below code snippet. I am using this approach to format phone number.
XSSFCellStyle currencyCellStyle = (XSSFCellStyle)workbook.CreateCellStyle();
XSSFDataFormat currencyDataFormat = (XSSFDataFormat)workbook.CreateDataFormat();
currrencyCellStyle.SetDataFormat(currencyDataFormat.GetFormat("00000.00")); //Formats: #####.##, 00000##.##
sometimes its tricky to find exact formatting in NPOI :). Please try below approaches
ICellStyle CellStyle = workbook.CreateCellStyle();
CellStyle.DataFormat = workbook.CreateDataFormat().GetFormat("number"); // or Number
or
CellStyle cellStyle = wb.createCellStyle();
cellStyle.setDataFormat(wb.getCreationHelper().createDataFormat().getFormat("#.#")); // or #####.## or number
I am trying to make a map by reading a text file line by line (because i cant find how to do that word by word). So I make a map00.txt that looks like "33000000111" (every number is one row, first 2 rows are number of columns and rows so matrix that I load it into looks like
000
000
111
). Now I am supposed to draw 3 tiles at the bottom (1=draw tile). I do so by drawing tile at its position in matrix * window height(width) / matrix number of rows(columns).
PROBLEM: i cant get the right parameters for current window width and height.
Code for loading tiles:
public int[,] LoadMatrix(string path)
{
StreamReader sr = new StreamReader(path);
int[,] a = new int[int.Parse(sr.ReadLine().ToString()),
int.Parse(sr.ReadLine().ToString())];
for(int i = 0; i < a.GetLength(0); i++)
for (int j = 0; j < a.GetLength(1); j++)
{ a[i, j] =int.Parse(sr.ReadLine().ToString()); }
sr.Close();
return a;
}
Code for drawing tiles:
public void DrawTiles(SpriteBatch sp, GraphicsDeviceManager gdm)
{
for(int i = 0; i < matrix.GetLength(0); i++)
for(int j = 0; j < matrix.GetLength(1); j++)
{
if (i == 1)
{
sp.Draw(tile,
new Rectangle(j * (gdm.PreferredBackBufferWidth / 3),//matrix.GetLength(1),
i * (gdm.PreferredBackBufferWidth / 3),//matrix.GetLength(0),
gdm.PreferredBackBufferWidth / matrix.GetLength(1),
gdm.PreferredBackBufferHeight / matrix.GetLength(0)),
Color.White);
}
}
}
but the result is that they are drawn about 40 pixels above the bottom of the screen!
and i tried with GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height(Width) but i get the same result. And when i put calculated numbers that should (in theory) be width/columns and heigth/rows i get what i want. So any suggestions would be VERY appriciated because i am stuck at this for a long time on google and Stack Overflow.
Here is a reworked version of your Draw code, which should work:
public void DrawTiles(SpriteBatch sp, GraphicsDeviceManager gdm)
{
//You would typically pre-compute these in a load function
int tileWidth = gdm.PreferredBackBufferWidth / matrix.GetLength(0);
int tileHeight = gdm.PreferredBackBufferWidth / matrix.GetLength(1);
//Loop through all tiles
for(int i = 0; i < matrix.GetLength(0); i++)
{
for(int j = 0; j < matrix.GetLength(1); j++)
{
//If tile value is not 0
if (matrix[i,j] != 0)
{
sp.Draw(tile, new Rectangle(i * tileWidth, j * tileHeight, tileWidth, tileHeight), Color.White);
}
}
}
}