i am new to PHPExcel learning from last two days and i am generating one report for the form input data. I have generated dynamically columns in the excel report but not able to set the first column as Index & last column as Date.
My code is:
// setting column names begin
$col = 1;
$row = 0;
$objPHPExcel->getActiveSheet()->setCellValueByColumnAndRow(0, $row, "Index No.");
foreach ($formInfo['fields'] as $fields) {
$objPHPExcel->getActiveSheet()->setCellValueByColumnAndRow($col, $row, $fields['grid-name']);
$col++;
}
$objPHPExcel->getActiveSheet()->setCellValueByColumnAndRow($col, $row, 'Date & Time of Input');
// setting column names ends!
Thanks in advance for response.
You have achieved the most. I just updated your code. Now it will work like as per you wish.
// Initializing last col variable
$endcolval = 0;
// Storing the value to First Column
$objPHPExcel->setActiveSheetIndex(0)
->setCellValueByColumnAndRow(0, 1, "Index");
// Storing the rest of the values from array to the respect indexes
foreach ($formInfo['fields'] as $col=>$fields)
{
$objPHPExcel->setActiveSheetIndex(0)
->setCellValueByColumnAndRow($col+1, 1, $fields['grid-name']);
// Using the above function you can able dynamically store the values to the cell.
// setCellValueByColumnAndRow(Column_Number, Row_Number, Value_To_Save);
$endcolval = $col+1;// Getting the last column number
}
// Assigning the Date to the Last Column.
$objPHPExcel->setActiveSheetIndex(0)
->setCellValueByColumnAndRow($endcolval+1, 1, "Date");
Related
I have a problem, i want to return the selected Rows values, and the columns separately, i found a method to return both of them using the function cell(row, column), but i want to get them separately
Here is my code :
QTableWidgetItem *c = new QTableWidgetItem();
QMap<QString,int> lists;
for(i=0;i<range.rowCount();++i){
for(int j=0;j<range.columnCount();++j){
c=item(i,j);// here i can return the Rows, Columns Data
QMessageBox::information(this,"",c->text());
}
}
As you can see this code is working, but i just want to return the Rows and the Columns separately so i can put them in my QMap<QString,int> list.
And the purpose of all this is to try to draw a piechart from the selected rows and columns
So Any help please
Here is what I understood from the comments, feel free to correct me and I'll update my answer if necessary.
COL1 | COL2
NAME | VALUE
So when you select a cell, you actually care about the whole row, a.k.a the name of the row and the value associated. If this is the case, it would make more sense to only allow the user to select whole rows, instead of cells. setSelectionBehavior(QAbstractItemView::SelectRows); should do the trick.
Provided that the name of the dataset is always in column 1, and the value in column 2, you should update your code with the snippet:
QTableWidgetItem *c; //Deleted memory leak in your code.
QMap<QString,double> myMap; //Don't name it a list if it is explicitly a map.
for(i=0;i<range.rowCount();++i){
QString dataName = item(i,0)->text();
int dataValue;
for(int j=1;j<range.columnCount();++j){
c=item(i,j);// here i can return the Rows, Columns Data
dataValue += c->text().toDouble();
//If you always have 2 columns only, dataValue will be the value you are looking for.
//If you can have more than 2 columns, dataValue will be the sum of all the cells located after the column 0, on the same row.
//Change this depending on how you want to treat those values.
QMessageBox::information(this,dataName,c->text());
}
myMap[dataName]=dataValue;
}
EDIT for QPieSeries, following this example:
QPieSeries *series = new QPieSeries();
QMap<QString,double>::iterator it = myMap.begin();
QMap<QString,double>::iterator end = myMap.end();
for(; it!=end; ++it){
series->append(it->key(), it->value());
}
QPieSlice *slice = series->slices().at(1);
slice->setExploded();
slice->setLabelVisible();
slice->setPen(QPen(Qt::darkGreen, 2));
slice->setBrush(Qt::green);
QChart *chart = new QChart();
chart->addSeries(series);
chart->setTitle("My Data");
chart->legend()->hide();
QChartView *chartView = new QChartView(chart);
chartView->setRenderHint(QPainter::Antialiasing);
/*change with your window here*/
yourWindow.setCentralWidget(chartView);
var res3 = dtPriorityMatrix.AsEnumerable()
.GroupBy(hour => hour.Field<int>("Hour"))
.OrderBy(item => item.Key)
.Select(item => new { Hour = item.Key });
I have a data table with 5 columns and around 200+ rows of data. One has hours (0-23) and others are Priority 1, Priority 2 and so on till Priority 4. I need to extract number of items of each priority for every hour. I need help with the Linq query as it is not my strong field. Thanks
You have to group by both columns. something like this
var query = source.GroupBy(x => new { x.Column1, x.Column2 });
so your code will be
var res3 = dtPriorityMatrix.AsEnumerable()
.GroupBy(hour =>new { hour= hour.Field<int>("Hour"), priority=hour.Field<int>("Priority")} )
.Select(item => new {count=item.count(), Hour = item.Key.hour, priority = item.Key.priority});\
edit
Reply to your comment:
when you have your results in a list, you can write it in anyway that you want.
the out put of the query is a list that contains hour, priority and count.
if you want it in 3 lines of string
string hLine="";
string pLine="";
string countLine="";
foreach(var item in res3)
{
hLine+= item.hour+" ";
pLine+= item.prioriy+" ";
countLine+= item.count+" ";
}
if you want to have them in a table or anything, use the same approach for filling your tables items
I have to merge the rows of excel using spreadsheet gear controls is it possible. Only specific rows of single column
All detail is being included in this screencast
The changes that has been done by me is
DataTable dt = (DataTable)ViewState["dtGrid"]
System.Random rd = new System.Random(DateTime.Now.Millisecond);
int MyValue = rd.Next(1000000, 99999999);
sUniqueName = MyValue.ToString();
// Create a new workbook.
SpreadsheetGear.IWorkbook workbook = SpreadsheetGear.Factory.GetWorkbook();
SpreadsheetGear.IRange cells = workbook.Worksheets[0].Cells;
cells.CopyFromDataTable(dt, SpreadsheetGear.Data.SetDataFlags.None);
cells.Rows[0, 0, 0, 51].Interior.Color = System.Drawing.Color.Navy;
cells.Rows[0, 0, 0, 51].Font.Color = System.Drawing.Color.White;
cells["A:R"].Columns.AutoFit();
string filename = string.Format("{0}-{1}-{2}", "AOMIndoorInventoryReport", DateTime.Now.ToString("MM-dd-yy"), sUniqueName);
Response.Clear();
Response.ContentType = "application/vnd.ms-excel";
Response.AddHeader("Content-Disposition", "attachment; filename=" + filename + ".xls");
workbook.SaveToStream(Response.OutputStream, SpreadsheetGear.FileFormat.Excel8);
Response.End();
What should be added?
You can merge cells by calling IRange.Merge() on the desired cells. Example:
cells["A7:A8"].Merge();
cells[8, 0, 22, 0].Merge();
UPDATE:
You've asked how to dynamically merge a range of cells based on adjacent rows in a column which have the same value. To accomplish this would require looping through each row in this column and comparing each cell's value with the previous value, merging when appropriate as you go down the column.
I am providing some sample code below which demonstrates one way in which you might go about this (there are certainly many other ways). I had to make some assumptions about your underlying data and requirements, so some modification on your end might be needed. Note the use of some handy methods under the IRange interface (see the IRange.Intersect(...) / Subtract(...) / Union(...) methods) which allow you to "interact" two IRanges to create a new third IRange.
...
// Create a new workbook and some local variables for convenience.
SpreadsheetGear.IWorkbook workbook = SpreadsheetGear.Factory.GetWorkbook();
SpreadsheetGear.IWorksheet worksheet = workbook.Worksheets[0];
SpreadsheetGear.IRange cells = worksheet.Cells;
// Copy data from DataTable to worksheet
cells.CopyFromDataTable(dt, SpreadsheetGear.Data.SetDataFlags.None);
// Here I am creating an IRange representing the used part of column a and without
// the header row, which I presume is in Row 1, and should not be included in this
// merging routine.
SpreadsheetGear.IRange usedColA = worksheet.UsedRange.Intersect(
cells["A:A"]).Subtract(cells["1:1"]);
// No point in attempting to merge cells if there's only a single row.
if (usedColA.RowCount > 1)
{
// Some variables to keep track of the content of the "current" and "previous"
// cells as we loop through "usedColA".
string prevCellVal = "";
string curCellVal = "";
// We'll use this variable to keep track of ranges which will need to be merged
// during the routine. Here I seed "mergeRange" with the first cell in usedColA.
SpreadsheetGear.IRange mergeRange = usedColA[0, 0];
// Loop through each cell in the used part of Column A.
foreach (SpreadsheetGear.IRange cell in usedColA)
{
// Get text of current "cell".
curCellVal = cell.Text;
// Your screenshot seems to indicate that you don't care about merging empty
// cells so this routine takes this into account. Either an empty cell or
// mismatched text from the "current" and "previous" cell indicate we should
// merge whatever cells we've accumulated in "mergeRange" and then reset this
// range to look for more ranges to merge further down the column.
if (curCellVal.Length == 0 || curCellVal != prevCellVal)
{
// Only merge if this range consists of more than 1 cell.
if (mergeRange.CellCount > 1)
mergeRange.Merge();
// Reset merged range to the "current" cell.
mergeRange = cell;
prevCellVal = curCellVal;
}
// If the current and previous cells contain the same text, add this "cell"
// to the "mergeRange". Note the use of IRange.Union(...) to combine two
// IRange objects into one.
else if (curCellVal == prevCellVal)
mergeRange = mergeRange.Union(cell);
}
// One last check for any cells to merge at the very end of the column.
if (mergeRange.CellCount > 1)
mergeRange.Merge();
}
...
I have csv file like this:
I need to show this csv file with gridview. But I must change format like this:
I must select distinct just date and mount columns and use date values on gridview columns.
How can I use values of csv file for Gridview columns?
Assuming that reading the CSV file is not an issue and you have already something like a List<ClassName>, DataTable or List<string[]>. I'm presuming that it's a List<String[]> where the first "column" is Date, the second Mount and the last % in my following approach.
You need real DateTimes and ints to be able to sum percents by date:
var formatProvider = new CultureInfo("de-DE"); // seems to be the correct format
var mountGroups = listOfStringArray
.Select(arr => new
{
Date = DateTime.Parse(arr[0].Trim(), formatProvider).Date,
Mount = arr[1].Trim(),
Percent = int.Parse(arr[2].Trim())
})
.GroupBy(x => x.Mount);
Now you have grouped by Mount, you just need to sum the percents for every day. You can use a DataTable as datasource for the GridView. Here's code that creates the table with the dynamic columns for every day:
var dataSource = new DataTable();
dataSource.Columns.Add("Mount");
var lastWeekColumns = Enumerable.Range(0, 7)
.Select(d => new DataColumn(DateTime.Today.AddDays(-6 + d).ToShortDateString(), typeof(int)))
.ToArray();
dataSource.Columns.AddRange(lastWeekColumns);
Following loop executes the LINQ query and fills the table:
foreach(var grp in mountGroups)
{
DataRow row = dataSource.Rows.Add();
row.SetField("Mount", grp.Key); // because: GroupBy(x => x.Mount);
foreach(DataColumn dayCol in lastWeekColumns)
{
DateTime day = DateTime.Parse(dayCol.ColumnName, formatProvider);
int sumPercent = grp.Where(x => x.Date == day)
.Select(x => x.Percent)
.DefaultIfEmpty(0) // fallback value for missing days
.Sum();
row.SetField(dayCol, sumPercent);
}
}
Now you just need to use it as datasource (AuthoGenerateColumns set to true)
grid.DataSource = dataSource;
grid.DataBind();
I am trying to use phpexcel to set the template purchase order .
I have set column 25 to 43 is for details of purchase item. It mean it will retrieve data from database and set all the value in column 25 to 43 .As addition ,these column only can fit for 6 item. I am facing problem when the purchase item is too many and cannot fit into the column that i had set.
My code is work,but it is too long. Anyone have a better solution?
after create both sheet,i have to set the other cellvalue one by one in both sheet.It make the code become very long.Appreciate for who can help.
$objPHPExcel->setActiveSheetIndex(0);
$result = mysql_query("SELECT purchasematerial.PONum,purchasematerial.QuoNum,purchasematerial.date, material.product,purchasematerial.description,purchasematerial.unit_price,purchasematerial.UOM,purchasematerial.qua ntity ,purchasematerial.amount FROM purchasematerial INNER JOIN material ON purchasematerial.product=material.id where PONum='$PONum'");
$col=25;
$num=1;
while($row = mysql_fetch_array($result)){
if($col<43){
$objPHPExcel->getActiveSheet()->setCellValue('AA11', $row['PONum']);
$date = new DateTime($row['date']);
$objPHPExcel->getActiveSheet()->setCellValue('AA12', $date->format('d-M-y'));
$objPHPExcel->getActiveSheet()->setCellValue('I45', '=AA12+7');
$QuoNum=$row['QuoNum'];
if ($QuoNum=='' || $QuoNum== null)
$objPHPExcel->getActiveSheet()->setCellValue('I47', "N/A");
else
$objPHPExcel->getActiveSheet()->setCellValue('I47', $row['QuoNum']);
$objPHPExcel->getActiveSheet()->setCellValue('A'.$col, $num);
$objPHPExcel->getActiveSheet()->setCellValue('B'.$col, $row['product']);
$objPHPExcel->getActiveSheet()->SetCellValue('J'.$col, $row['description']);
$objPHPExcel->getActiveSheet()->SetCellValue('S'.$col, $row['unit_price']);
$objPHPExcel->getActiveSheet()->setCellValue('V'.$col, $row['UOM']);
$objPHPExcel->getActiveSheet()->SetCellValue('Y'.$col, $row['quantity']);
$objPHPExcel->getActiveSheet()->SetCellValue('AB'.$col, $row['amount']);
$col=$col+3;
$num++;
}
else{
$objPHPExcel->createSheet();
$objPHPExcel->setActiveSheetIndex(1);
$col=25;
$objPHPExcel->getActiveSheet()->setCellValue('AA11', $row['PONum']);
$date = new DateTime($row['date']);
$objPHPExcel->getActiveSheet()->setCellValue('AA12', $date->format('d-M-y'));
$objPHPExcel->getActiveSheet()->setCellValue('I45', '=AA12+7');
$QuoNum=$row['QuoNum'];
if ($QuoNum=='' || $QuoNum== null)
$objPHPExcel->getActiveSheet()->setCellValue('I47', "N/A");
else
$objPHPExcel->getActiveSheet()->setCellValue('I47', $row['QuoNum']);
$objPHPExcel->getActiveSheet()->setCellValue('A'.$col, $num);
$objPHPExcel->getActiveSheet()->setCellValue('B'.$col, $row['product']);
$objPHPExcel->getActiveSheet()->SetCellValue('J'.$col, $row['description']);
$objPHPExcel->getActiveSheet()->SetCellValue('S'.$col, $row['unit_price']);
$objPHPExcel->getActiveSheet()->setCellValue('V'.$col, $row['UOM']);
$objPHPExcel->getActiveSheet()->SetCellValue('Y'.$col, $row['quantity']);
$objPHPExcel->getActiveSheet()->SetCellValue('AB'.$col, $row['amount']);
$col=$col+3;
$num++;
}
}
$objPHPExcel->setActiveSheetIndex(0);
$objPHPExcel->getActiveSheet()->getStyle('I45')->getNumberFormat()- >setFormatCode(PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX15);
$objPHPExcel->getActiveSheet()->setCellValue('AC1', 'WEEKNUM(I45)');
$objPHPExcel->getActiveSheet()->setCellValue('Q44', 'TOTAL');
$objPHPExcel->getActiveSheet()->SetCellValue('Y44','RM');
$objPHPExcel->getActiveSheet()->SetCellValue('AB44', '=SUM(AB25:AB43)');
$objPHPExcel->getActiveSheet()->getStyle('Q44')->getFont()->setBold(true);
$objPHPExcel->getActiveSheet()->getStyle('Y44')->getFont()->setBold(true);
$objPHPExcel->getActiveSheet()->getStyle('AA44')->getFont()->setBold(true);
$objPHPExcel->setActiveSheetIndex(1);
$objPHPExcel->getActiveSheet()->getStyle('I45')->getNumberFormat()->setFormatCode(PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX15);
$objPHPExcel->getActiveSheet()->setCellValue('AC1', 'WEEKNUM(I45)');
$objPHPExcel->getActiveSheet()->setCellValue('Q44', 'TOTAL');
$objPHPExcel->getActiveSheet()->SetCellValue('Y44','RM');
$objPHPExcel->getActiveSheet()->SetCellValue('AB44', '=SUM(AB25:AB43)');
$objPHPExcel->getActiveSheet()->getStyle('Q44')->getFont()->setBold(true);
$objPHPExcel->getActiveSheet()->getStyle('Y44')->getFont()->setBold(true);
$objPHPExcel->getActiveSheet()->getStyle('AA44')->getFont()->setBold(true);
One way might be to use the fluent interface.
Instead of
$objPHPExcel->getActiveSheet()->setCellValue('I47', $row['QuoNum']);
$objPHPExcel->getActiveSheet()->setCellValue('A'.$col, $num);
$objPHPExcel->getActiveSheet()->setCellValue('B'.$col, $row['product']);
$objPHPExcel->getActiveSheet()->SetCellValue('J'.$col, $row['description']);
$objPHPExcel->getActiveSheet()->SetCellValue('S'.$col, $row['unit_price']);
$objPHPExcel->getActiveSheet()->setCellValue('V'.$col, $row['UOM']);
$objPHPExcel->getActiveSheet()->SetCellValue('Y'.$col, $row['quantity']);
$objPHPExcel->getActiveSheet()->SetCellValue('AB'.$col, $row['amount']);
do
$objPHPExcel->getActiveSheet()->setCellValue('I47', $row['QuoNum'])
->setCellValue('A'.$col, $num)
->setCellValue('B'.$col, $row['product'])
->SetCellValue('J'.$col, $row['description'])
->SetCellValue('S'.$col, $row['unit_price'])
->setCellValue('V'.$col, $row['UOM'])
->SetCellValue('Y'.$col, $row['quantity'])
->SetCellValue('AB'.$col, $row['amount']);
so that you're not constantly calling $objPHPExcel->getActiveSheet()
For setting the second sheet, as the cells are identical to the first; you could create a function to set the cell values and just call that function twice (basic PHP 101). Alternatively, you could set the cells for the first sheet, then clone that sheet and set the clone as the second sheet.