PHPExcel Add new rows without override existing info - add

Is possible add new rows in the middle of this sheet?
...without affect or overwrite the information at the bottom of the document?
I know that is possible create the bottom info manually, but I have to upload this Excel each month (with different header) and set the start row.
I've tried copy the last rows but duplicateStyle doesn't copy borders and backgrounds
# library
$this->load->library('excel');
$path = './assets/files/uploads/form.xls';
$excel = PHPExcel_IOFactory::load( $path );
$excel->setActiveSheetIndex(1);
$row = 10;
$total = 25;
if( $total >= 20 )
{
$cellValues = $excel->getActiveSheet()->rangeToArray( 'A30:L32' );
$excel->getActiveSheet()->fromArray( $cellValues, null, 'A33' );
$excel->getActiveSheet()->duplicateStyle( $excel->getActiveSheet()->getStyle( 'A30:L30'), 'A32:L32' );
}

There is a Worksheet method called insertNewRowBefore() (and a corresponding method for columns called insertNewColumnBefore()) that do this.
$excel->getActiveSheet()->insertNewRowBefore(10, 5);
will insert 5 new rows into the active worksheet, before row 10... effectively, it pushes row 10 down to row 15, row 11 down to row 16, row 12 down to row 17, etc; adjusting formulae and other cell references accordingly.
Likewise
$excel->getActiveSheet()->insertNewColumnBefore('B');
will insert a single new column (the default for both insertNewRowBefore() and insertNewColumnBefore() is a single row or a single column) before column B.
In the examples folder, 05featuredemo.php and 30template.php demonstrate the use of these methods
And
$excel->getActiveSheet()->duplicateStyle(
$excel->getActiveSheet()->getStyle('A30'),
'A31:A100'
);
should copy all style elements (including borders and background) from a single cell to range of cells; but it won't copy different styles from a range of cells to a new range of cells.

Related

Reapet n times each rows from query in google sheets

I try to have an output by query - reapeting each rows by formula in google sheets after match the term (term is text from cell - after choose from drop down list)
I'd like to Select a,b,c,f,g,h etc) and reapeting each column 7 times.
I have two formulas.
Now by Query formula on Output i have each row only one time.
And ArrayFormula to repeating - but it works only for 1 column
I'd like to combine 2 formulas below to choose all column and repeat each row 7 times.
=QUERY(MY_DICTIONARY!A5:F100; "SELECT a,b,c,f,g,h, WHERE A='"&F3&"'")
=SORT(TRIM(TRANSPOSE(SPLIT(QUERY(ARRAYFORMULA(
REPT(A8:A50&"♠"; 7)); ;999^99); "♠"))); 1; 0)
I will be extremely happy to any help.
maybe It will possible to combine 2 formulas into 1?
Edit 09:08
I add example file to show my problem.
example google sheet
I'm trying to combine Array formula for all columns.
But I discovered that it works well enough as a single Array of range each (D:D), (E:E), (F:F), (G:G).
=ARRAYFORMULA(TRIM(TRANSPOSE(SPLIT(QUERY(
REPT(D4:D100&"♠"; 7); ;99^99); "♠"))))
=ARRAYFORMULA(TRIM(TRANSPOSE(SPLIT(QUERY(
REPT(E4:E100&"♠"; 7); ;99^99); "♠"))))
=ARRAYFORMULA(TRIM(TRANSPOSE(SPLIT(QUERY(
REPT(F4:F100&"♠"; 7); ;99^99); "♠"))))
=ARRAYFORMULA(TRIM(TRANSPOSE(SPLIT(QUERY(
REPT(G4:G100&"♠"; 7); ;99^99); "♠"))))

How to keep the Row Height constant when a table is pushed down on the sheet

I have a sheet with 2 tables.
Each table has a header that I want to be a height of 30 while all table rows are the standard 15.
When I add a row to the top table, the bottom table gets pushed down.
The header Height on the bottom table picks up the height of the new spreadsheet row.
Is there a way to make the bottom table keep its header height at 30?
Here is my code to add rows to the top table.
Set tblAssemblies = Worksheets("Summary").ListObjects("Table1")
Count = 1
Do
tblAssemblies.ListRows.Add AlwaysInsert:=True
Count = Count + 1
Loop While Count <= Target.Value - tblAssembliesRows
This pushed the bottom table down, but not the formatting of the sheet row for the header height.
Any Ideas?
Rich
HeaderRowRange.RowHeight
I've noticed, and you didn't mention, that the '30-height-row moves' into the first table. This should be corrected, too.
Option Explicit
Sub HeaderRowRangeRowHeight()
With Worksheets("Summary")
.ListObjects(2).HeaderRowRange.RowHeight = 30
.ListObjects(1).DataBodyRange.RowHeight = 15
.ListObjects(1).TotalsRowRange.RowHeight = 15
End With
End Sub
I am not sure where Target's range is in reference to the header of the table in question, but you could do something like
rows(target.row).rowheight = 22.5
If your header, for example, is always three rows below the Target, then you would just add 3:
rows(target.row + 3).rowheight = 22.5

Apache POI - How to set correct column width in Word table

I have an existing Word document containing a table. The first row of the table has two cells, but all the other rows have four cells and each cell has a different width.
I need to insert new rows via POI that also have four cells with widths that match those of the existing 4-cell rows.
The basic code is:
XWPFTable table = doc.getTableArray(0);
XWPFTableRow oldRow = table.getRow(2);
table.insertNewTableRow(3);
XWPFTableRow newRow = table.getRow(3);
XWPFTableCell cell;
for (int i = 0; i < oldRow.getTableCells().size(); i++) {
cell = newRow.createCell();
CTTblWidth cellWidth = cell.getCTTc().addNewTcPr().addNewTcW();
BigInteger width = oldRow.getCell(i).getCTTc().getTcPr().getTcW().getW();
cellWidth.setW(width); // sets width
XWPFRun run = cell.getParagraphs().get(0).createRun();
run.setText("NewRow C" + i);
}
The result of this is that row 3 has four cells but their widths do not match those of row 2. The total new row width ends up being the same as the total width of the first three cells of row 2. (Sorry, I don't know how to paste the Word table here).
However, if I first manually edit the source document so that the first table row also has four cells, then everything works perfectly. Similarly, if I get a reference to an existing row and add it to the table, then the cell widths are also correct (but I have the same row object twice so can't modify it).
It seems that the number of cells in the first row influences how other rows are inserted. Does this make sense to anyone and can you suggest how to override it? Also, is there a document anywhere that I can study to understand how this works? Thanks.
Accordiing to your mention: "The first row of the table has two cells, but all the other rows have four cells and each cell has a different width." I suspect this will be a very messy table. Although Word is supporting such tables, I would try to avoid such. But if it must be, you need to know that there is a table grid also for those messy tables. Unzip the *.docx and have a look at /word/document.xml there you will find it.
So if we want to insert rows into such messy tables, we also must respect the table grid. For this there is a GridSpan element in the CTTcPr. This we must also copy from the oldRow and not only copy the CTTblWidth.
Also the CTTblWidth has not only a width but also a type. This we also should copy.
Example:
The source.docx looks like this:
As you see the table grid has 10 columns in total. "Cell 2 1" spans 3 columns, "Cell 2 2" spans 3 columns, "Cell 2 3" spans 0 columns (is its own column), "Cell 2 4" spans 3 columns.
With code:
import java.io.*;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblWidth;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr;
import java.math.BigInteger;
public class WordInsertTableRow {
public static void main(String[] args) throws IOException, InvalidFormatException {
XWPFDocument doc = new XWPFDocument(new FileInputStream("source.docx"));
XWPFTable table = doc.getTableArray(0);
XWPFTableRow oldRow = table.getRow(2);
table.insertNewTableRow(3);
XWPFTableRow newRow = table.getRow(3);
XWPFTableCell cell;
for (int i = 0; i < oldRow.getTableCells().size(); i++) {
cell = newRow.createCell();
CTTcPr ctTcPr = cell.getCTTc().addNewTcPr();
CTTblWidth cellWidth = ctTcPr.addNewTcW();
cellWidth.setType(oldRow.getCell(i).getCTTc().getTcPr().getTcW().getType()); // sets type of width
BigInteger width = oldRow.getCell(i).getCTTc().getTcPr().getTcW().getW();
cellWidth.setW(width); // sets width
if (oldRow.getCell(i).getCTTc().getTcPr().getGridSpan() != null) {
ctTcPr.setGridSpan(oldRow.getCell(i).getCTTc().getTcPr().getGridSpan()); // sets grid span if any
}
XWPFRun run = cell.getParagraphs().get(0).createRun();
run.setText("NewRow C" + i);
}
doc.write(new FileOutputStream("result.docx"));
doc.close();
System.out.println("Done");
}
}
The result.docx looks like:

Making Google sheets for entries made today, this week, and this month

I have a Google sheet that pulls information from a form. The form inputs a timestamp and IDnumber into a spreadsheet. I need to make different sheets to show which of these entries were made Today, This week, and This month.
Example
Timestamp ID
12/1/2012 12345
12/1/2012 55555
12/4/2012 98765
12/15/2012 74823
I need to make a sheet that puts ID 12345 and 55555 into one "DAILY" Sheet, IDs 12345, 55555, and 98765 into a "WEEKLY" sheet, and one that has all of these in a "MONTHLY" sheet.
Here's what I would do...
Add today's date somewhere in the sheet (let's say cell D2) by inputting '=Today()' in D2.
In column C, next to your first two columns, add formulas to calculate the number of days between the date in column A and today's date. In row 2, the formula would look like this...
=DATEDIF(A2,D2,"D")
Then, using the script editor in the spreadsheet, I would write a script that looks at column C and writes values from column A and B depending on that value. I haven't tested the script below, but I think it's what you would need. Essentially, it loops through column C of your results sheet. Depending on the value (days from today), that row is pushed to an array for each range. Then I cleared the sheet for that range before setting the values of the array. I hope this helps!
function daysBetween(){
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet(),
formResultsSheet = spreadsheet.getSheetByName("Form Results"),
daySheet = spreadsheet.getSheetByName("Today"),
weekSheet = spreadsheet.getSheetByName("This Week"),
monthSheet = spreadsheet.getSheetByName("This Month"),
allData = formResultsSheet.getDataRange().getValues(),
dayResults = [],
weekResults = [],
monthResults = [];
for (var i = 0; i < formResultsSheet.getLastRow(); i++) {
if (allData[i][2] === 0){
dayResults.push(allData[i])
} else if (allData[i][2] > 0 && allData[i][2] <= 7) {
weekResults.push(allData[i])
} else if (allData[i][2] > 7 && allData[i][2] <= 30) {
monthResults.push(allData[i])
}
}
daySheet.getDataRange().clear()
daySheet.getRange(1,1,dayResults.length,dayResults[0].length).setValues(dayResults)
weekSheet.getDataRange().clear()
weekSheet.getRange(1,1,weekResults.length,weekResults[0].length).setValues(weekResults)
monthSheet.getDataRange().clear()
monthSheet.getRange(1,1,monthResults.length,monthResults[0].length).setValues(monthResults)
}

Read from a specific row onwards from Excel File

I have got a Excel file having around 7000 rows approx to read. And Excel file contains Table of Contents and the actual contents data in details below.
I would like to avoid all rows for Table of Content and start from actual content data to read. This is because if I need to read data for "CPU_INFO" the loop and search string occurrence twice 1] from Table of Content and 2] from actual Content.
So I would like to know if there is any way I can point to Start Row Index to start reading data content for Excel File , thus skipping whole of Table Of Content Section?
As taken from the Apache POI documentation on iterating over rows and cells:
In some cases, when iterating, you need full control over how missing or blank rows or cells are treated, and you need to ensure you visit every cell and not just those defined in the file. (The CellIterator will only return the cells defined in the file, which is largely those with values or stylings, but it depends on Excel).
In cases such as these, you should fetch the first and last column information for a row, then call getCell(int, MissingCellPolicy) to fetch the cell. Use a MissingCellPolicy to control how blank or null cells are handled.
If we take the example code from that documentation, and tweak it for your requirement to start on row 7000, and assuming you want to not go past 15k rows, we get:
// Decide which rows to process
int rowStart = Math.min(7000, sheet.getFirstRowNum());
int rowEnd = Math.max(1500, sheet.getLastRowNum());
for (int rowNum = rowStart; rowNum < rowEnd; rowNum++) {
Row r = sheet.getRow(rowNum);
int lastColumn = Math.max(r.getLastCellNum(), MY_MINIMUM_COLUMN_COUNT);
for (int cn = 0; cn < lastColumn; cn++) {
Cell c = r.getCell(cn, Row.RETURN_BLANK_AS_NULL);
if (c == null) {
// The spreadsheet is empty in this cell
} else {
// Do something useful with the cell's contents
}
}
}

Resources