I am trying to draw a table in word document using Apache POI XWPF. But the table is drawing with double height rows like this
Here is my source
XWPFTable table = document.createTable(5, 1);
for (Test t : tests) {
XWPFTableRow row = table.getRow(k - 1);
XWPFTableCell cell = row.getCell(0);
XWPFParagraph ansParagraph = new XWPFParagraph(cell.getCTTc().insertNewP(0), cell);
XWPFRun ansRun = ansParagraph.createRun();
ansRun.setText(k + ") ");
cell.addParagraph(ansParagraph);
k++;
}
how can I reduced the height of row.
When you create a table in Apache POI XWPF it already has a blank paragraph in every cell.
You are getting double height rows because you are also adding a paragraph in it.
So you replace the line
XWPFParagraph ansParagraph = new XWPFParagraph(cell.getCTTc().insertNewP(0), cell);
with
XWPFParagraph ansParagraph = cell.getParagraphs().get(0);
And remove the line
cell.addParagraph(ansParagraph);
Then it will work OK.
Related
I am trying in the code below to generate a report with side by side two images and a splited table but I get an error. Why this error occur?
Code:
close all;
clear all;
clc;
import mlreportgen.report.*
import mlreportgen.dom.*
import mlreportgen.utils.*
Name = {'A';'B';'C';'D';'E';'A';'B';'C';'D';'E'};
codeA = [8;3;8;0;4;8;3;8;0;4];
Height = [1;8;4;7;8;8;3;1;0;4];
Weight = [6;2;1;4;5;8;3;1;1;4];
T = table(Name,codeA,Height,Weight,codeA,Height,Weight,codeA,Height,Weight);
Image1 = Image(which('coins.png'));
Image2 = Image(which('sevilla.jpg'));
rpt = Report("myPDF","pdf");
imgStyle = {ScaleToFit(true)};
Image2.Style = imgStyle;
Image1.Style = imgStyle;
lot = Table({Image2, ' ', Image1});
lot.entry(1,1).Style = {Width('3.2in'), Height('3in')};
lot.entry(1,2).Style = {Width('.2in'), Height('3in')};
lot.entry(1,3).Style = {Width('3.2in'), Height('3in')};
lot.Style = {ResizeToFitContents(false), Width('100%')};
add(rpt, lot);
chapter = Chapter("Title",'Table Report');
table = FormalTable(T);
table.Border = 'Solid';
table.RowSep = 'Solid';
table.ColSep = 'Solid';
para = Paragraph(['The table is sliced into two tables, '...
'with the first column repeating in each table.']);
para.Style = {OuterMargin('0in','0in','0in','12pt')};
para.FontSize = '14pt';
add(chapter,para)
slicer = TableSlicer("Table",table,"MaxCols",5,"RepeatCols",1);
totcols = slicer.MaxCols - slicer.RepeatCols;
slices = slicer.slice();
for slice=slices
str = sprintf('%d repeating column and up to %d more columns',...
slicer.RepeatCols,totcols);
para = Paragraph(str);
para.Bold = true;
add(chapter,para)
add(chapter,slice.Table)
end
add(rpt,chapter)
close(rpt)
rptview(rpt)
Error:
*Index exceeds the number of array elements. Index must not exceed 10.
Error in try1 (line 26)
lot.entry(1,1).Style = {Width('3.2in'), Height('3in')};*
You define the variable
Height = [1;8;4;7;8;8;3;1;0;4];
Then you try and use the report gen function Height
lot.entry(1,1).Style = {Width('3.2in'), Height('3in')};
Because you've shadowed the Height function with a variable, MATLAB is trying to get the element of this array at index '3in', which is either nonsensical or (via some implicit ASCII conversion) is way out of range.
Per my comment on your previous question, I think the way the documentation suggests the report gen functions are imported is bad practice. By using import mlreportgen.dom.* you are putting all of the nicely name-spaced functions from that package into the common area, and in this case it has caused an unclear clash between two things. So there are two options:
Use the namespaced version of Height (and Width), if you did this with all of the report gen functions you would not need the import. The nice side-effect is you get tab-completion when typing the various functions from this package
lot.entry(1,1).Style = {mlreportgen.dom.Width('3.2in'), mlreportgen.dom.Height('3in')};
Sure, you code is longer, but it is more explicit.
... or ...
Simply don't define a variable called Height. Rename this and everything else can stay the same.
I try to read the values from a cell as a String (as one would see it in Excel). I reads from a xlsx (XSSFWorkbook) using Apache POI 3.15.
My goal is e.g. to omit decimal point and trailing zeros if the cell contains an integer. This works for CellType.NUMERIC:
val dataFormatter = new DataFormatter(true) // set emulateCsv to true
val stringValue = dataFormatter.formatCellValue(cell)
If I use the same code for CellType.FORMULA cell (e.g. a cell which references another "integer" cell), it just gives me the formula as a string instead of its computed value.
How can I get value of the formula-cell as displayed in Excel displays?
You need to "evaluate" cells in order to get the result of formulas. This is not done automatically by POI as it can be a heavy operation and often will not be necessary.
See http://poi.apache.org/spreadsheet/eval.html for details, basically you create a FormulaEvaluator and retrieve a CellValue for the Cell in question
FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator();
...
CellValue cellValue = evaluator.evaluate(cell);
Thanks to Centic and Raphael I ended up using the concept with NumberFormat to fix an issue, this is Java but I am sure it can easily be converted to Scala
The issue is around numbers with decimal places which produces scientific decimal points.
This was only required when converting Apache POI XLS / XLSX to CSV format
//Create an evaluator from current work book
FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator();
// Cell cell2 = evaluator.evaluateInCell(cell);
// As per above get CellValue
CellValue cellValue = evaluator.evaluate(cell);
//Get Double Value of formula which may contain E numbers
Double value = cellValue.getNumberValue();
// This gets numberFormat (below function) and assigns correct formatting to it
NumberFormat formatter = getNumberFormat(value);
//This should now be string value of number with correct decimal place values (non scientific)
formatter.format(value)
/**
* getNumberFormat takes number and either assigns #0
* if no decimal places or
* depending on how many numbers after decimal place assigns correct format
*/
public static NumberFormat getNumberFormat(Double value) {
String v = value.toString();
String format = "#0";
// This fixes scientific value issue
if (v.contains(".")) {
int decimals = v).substring(v.indexOf(".") + 1).length();
//Calls generateNumberSigns based on decimal places in given double
String numberSigns = generateNumberSigns(decimals);
format = "0." + numberSigns;
}
return new DecimalFormat(format);
}
/**
* This will generate correct formula for amount of decimal places
*/
public static String generateNumberSigns(int n) {
String s = "";
for (int i = 0; i < n; i++) {
s += "#";
}
return s;
}
I am playing around with pie charts in d3.js. I want to have several charts working at the same time, and be able to select one or another by their class. The idea is that there is a main chart, and by clicking in the diferent areas, new charts should emerge displaying sub-categories.
Here's the piece of code that is giving me a headache:
// myPie has been deffined previously as --> var myPie = d3.layout.pie();
// dataPie is an array such as --> [2,3,1,2]
// level2 is just an array of arrays containing the sub-sets of data I want to display in the pie-charts
var myArcs = mySvg.selectAll("g")
.data(myPie(dataPie))
.enter()
.append("g")
.attr("class","arc")
.attr("transform","translate(" + xCenter +"," + yCenter + ")" )
// Appending other arcs
for(i=0; i<allData.length; i++){
var dataLabels_i = [];
var dataPie_i = [];
for(j=0; j<level2[i].length; j++){
dataLabels_i[j] = level2[i][j][0]
dataPie_i[j] = level2[i][j][1]
}
var arcArray =[];
var rectArray =[];
arcArray[i] = mySvg.selectAll("g")
.data(myPie(dataPie_i))
.enter()
.append("g")
.attr("class","arc_"+i)
.attr("transform","translate(" + xCenter +"," + yCenter + ")" )
}
The first piechart is generated nicely (it's ploted later on), but the charts that I generate in the for loop won't. I suspect that it has to do with the fact that I am generating "g's" in an svg that already has some "g's", so there is some sort of conflict and they override? I try to cope with this by assigning different classes to each chart.
Any idea?
Thanks to everyone!
As Mark mentioned, while trying to generating charts for the loop, you should use a more specific selector instead of using the general g selector, such as "arc_" + i if that's the different classes you want to assign.
The reason why using <g> selector doesn't generate a new chart is that when you selectAll("g") and bind data by myPie(dataPie_i) in the loop, d3 will find the previous g generated from the first piechart, therefore the enter() selection won't be updated, it's empty in this case, <g> won't be appended. More details about join data can be found here.
Ahab stated in 2010: the complex looking number based on the Timestamp has one important property, the number can not change when rows are deleted or inserted.
As long as the submitted data is not changed by inserting deleting rows the simple formula =ArrayFormula(ROW(A2:A) - 1) may be the easiest one to use.
For other situations there is no nice reliable solution. :(
Now we live in 2015. Maybe times have changed?
I need a reliable way to number entries using a form.
Maybe a script can do the trick? A script that can add 1 to each entry?
That certain entry has to keep that number even when rows are deleted or inserted.
I created this simple spreadsheet in which I added 1,2, and 3 manually,please have a look:
https://docs.google.com/spreadsheets/d/1H9EXns8-7m9oLbCrTyIZhLKXk6TGxzWlO9pOvQSODYs/edit?usp=sharing
The script has to find the maximum of the former entries, which is 3, and then add 1 automatically.
Who can help me with this?
Grtz, Bij
Maybe a script can do the trick? A script that can add 1 to each
entry?
Yes, that would be what you need to resort to. I took the liberty of entering this in your example ss:
function onEdit(e) {
var watchColumns = [1, 2]; //when text is entered in any of these columns, auto-numbering will be triggered
var autoColumn = 3;
var headerRows = 1;
var watchSheet = "Form";
var range = e.range;
var sheet = range.getSheet();
if (e.value !== undefined && sheet.getName() == watchSheet) {
if (watchColumns.indexOf(range.getColumn()) > -1) {
var row = range.getRow();
if (row > headerRows) {
var autoCell = sheet.getRange(row, autoColumn);
if (!autoCell.getValue()) {
var data = sheet.getDataRange().getValues();
var temp = 1;
for (var i = headerRows, length = data.length; i < length; i++)
if (data[i][autoColumn - 1] > temp)
temp = data[i][autoColumn - 1];
autoCell.setValue(temp + 1);
}
}
}
}
}
For me the best way is to create a query in a second sheet pulling everything from form responses in to second column and so on. then use the first column for numbering.
In your second sheet B1 you would use:
=QUERY(Form!1:1004)
In your second sheet A2 you would use:
=ARRAYFORMULA(if(B2:B="",,Row(B2:B)-1))
I made a second sheet in your example spreadsheet, have a look at it.
My code below is lost when opening PDF file which has only one column on the front page and more than 1 column on other pages.
Someone can tell me what I'm doing wrong?
Below my code:
PdfReader pdfreader = new PdfReader(pathNmArq);
ITextExtractionStrategy strategy = new SimpleTextExtractionStrategy();
for (int page=1; page <= lastPage; page++)
{
extractText = PdfTextExtractor.GetTextFromPage(pdfreader, page, strategy);
extractText = Encoding.UTF8.GetString(ASCIIEncoding.Convert(Encoding.Default, Encoding.UTF8, Encoding.Default.GetBytes(extractText)));
/ / ...
}
You use the SimpleTextExtractionStrategy. This strategy assumes that the text drawing instructions in the PDF are sorted by the reading order. In your case that does not seem to be the case.
If you cannot count on the PDF containing drawing operations in reading order but are only using iText text extraction strategies from the distribution, you have to know areas which constitute a single column. If a page contains multiple columns, you have to use RegionTextRenderFilter to restrict to a column and then use the LocationTextExtractionStrategy.
PS: What exactly is your intention in that
extractText = Encoding.UTF8.GetString(ASCIIEncoding.Convert(Encoding.Default, Encoding.UTF8, Encoding.Default.GetBytes(extractText)));
line?