Could someone please explain to me how to properly use the Anchors when creating cell comments? Mine were working, but the spread sheet changed and I am having issues getting my cell comments to appear. This is the code I was using that worked:
Comment c = drawing.createCellComment (new HSSFClientAnchor(0, 0, 0, 0, (short)4, 2, (short)6, 5));
That was found mostly by experimenting around. Looking at the api for it doesn't exactly make it any clearer.
Based on the quick start guide I have also tried the following with no luck:
ClientAnchor anchor = chf.createClientAnchor();
Comment c = drawing.createCellComment(anchor);
c.setString(chf.createRichTextString(message));
A bit late, but this will probably work (it works for me, while the Apache POI example from the quick start also didn't work for me):
public void setComment(String text, Cell cell) {
final Map<Sheet, HSSFPatriarch> drawingPatriarches = new HashMap<Sheet, HSSFPatriarch>();
CreationHelper createHelper = cell.getSheet().getWorkbook().getCreationHelper();
HSSFSheet sheet = (HSSFSheet) cell.getSheet();
HSSFPatriarch drawingPatriarch = drawingPatriarches.get(sheet);
if (drawingPatriarch == null) {
drawingPatriarch = sheet.createDrawingPatriarch();
drawingPatriarches.put(sheet, drawingPatriarch);
}
Comment comment = drawingPatriarch.createComment(new HSSFClientAnchor(0, 0, 0, 0, (short) 4, 2, (short) 6, 5));
comment.setString(createHelper.createRichTextString(text));
cell.setCellComment(comment);
}
Erik Pragt
The following code works for me for Office 2007 (xlsx) format files. Figured this out from POI guide
http://poi.apache.org/spreadsheet/quick-guide.html#CellComments
and
How to set comments for 3 cells using apache poi
protected void setCellComment(Cell cell, String message) {
Drawing drawing = cell.getSheet().createDrawingPatriarch();
CreationHelper factory = cell.getSheet().getWorkbook()
.getCreationHelper();
// When the comment box is visible, have it show in a 1x3 space
ClientAnchor anchor = factory.createClientAnchor();
anchor.setCol1(cell.getColumnIndex());
anchor.setCol2(cell.getColumnIndex() + 1);
anchor.setRow1(cell.getRowIndex());
anchor.setRow2(cell.getRowIndex() + 1);
anchor.setDx1(100);
anchor.setDx2(100);
anchor.setDy1(100);
anchor.setDy2(100);
// Create the comment and set the text+author
Comment comment = drawing.createCellComment(anchor);
RichTextString str = factory.createRichTextString(message);
comment.setString(str);
comment.setAuthor("Apache POI");
// Assign the comment to the cell
cell.setCellComment(comment);
}
Related
How can I strikethrough diagonally a cell in excel using Apache poi?
I want to get something like this:
I have tried:
cell.getCellStyle().setFillPattern(CellStyle.THIN_BACKWARD_DIAG)
but then the cell is having many diagonal lines instead of one from top right to bottom left.
Edit:
This is how I create the workbook:
Workbook workbook = new SXSSFWorkbook(SXSSFWorkbook.DEFAULT_WINDOW_SIZE);
Sheet sheet = workbook.createSheet("Test");
Then creating the columns and the rows, I don't see there any special to show.
Any idea what can I do?
Sorry for my previous answer, currently there is no diagonal border available readily in apache poi, though we can write our own custom method. You can use below method which will add a diagonal border in a cell.
public static void setDiagonal(StylesTable stylesSource, CTXf cellXtraFormating, ThemesTable theme) {
CTBorder ct = CTBorder.Factory.newInstance();
CTBorderPr pr = ct.addNewDiagonal();
ct.setDiagonalUp(true);
pr.setStyle(STBorderStyle.Enum.forInt(BorderFormatting.BORDER_THIN + 1));
int idx = stylesSource.putBorder(new XSSFCellBorder(ct, theme));
cellXtraFormating.setBorderId(idx);
cellXtraFormating.setApplyBorder(true);
}
call the above method in your class like this
CellStyle cs = workbook.createCellStyle();
StylesTable styleSource = ((XSSFWorkbook) workbook).getStylesSource();
ThemesTable theme = styleSource.getTheme();
CTXf cellXtraFormating = ((XSSFCellStyle) cs).getCoreXf();
-------your custom code---------
setDiagonal(styleSource, cellXtraFormating, theme);
cell.setCellStyle(cs);
I hope this answers your question
I have a C# application that generates a PDF invoice. In this invoice is a table of items and prices. This is generated using a PdfPTable and PdfPCells.
I want to be able to right-align the price column but I cannot seem to be able to - the text always comes out left-aligned in the cell.
Here is my code for creating the table:
PdfPTable table = new PdfPTable(2);
table.TotalWidth = invoice.PageSize.Width;
float[] widths = { invoice.PageSize.Width - 70f, 70f };
table.SetWidths(widths);
table.AddCell(new Phrase("Item Name", tableHeadFont));
table.AddCell(new Phrase("Price", tableHeadFont));
SqlCommand cmdItems = new SqlCommand("SELECT...", con);
using (SqlDataReader rdrItems = cmdItems.ExecuteReader())
{
while (rdrItems.Read())
{
table.AddCell(new Phrase(rdrItems["itemName"].ToString(), tableFont));
double price = Convert.ToDouble(rdrItems["price"]);
PdfPCell pcell = new PdfPCell();
pcell.HorizontalAlignment = PdfPCell.ALIGN_RIGHT;
pcell.AddElement(new Phrase(price.ToString("0.00"), tableFont));
table.AddCell(pcell);
}
}
Can anyone help?
I'm the original developer of iText, and the problem you're experiencing is explained in my book.
You're mixing text mode and composite mode.
In text mode, you create the PdfPCell with a Phrase as the parameter of the constructor, and you define the alignment at the level of the cell. However, you're working in composite mode. This mode is triggered as soon as you use the addElement() method. In composite mode, the alignment defined at the level of the cell is ignored (which explains your problem). Instead, the alignment of the separate elements is used.
How to solve your problem?
Either work in text mode by adding your Phrase to the cell in a different way.
Or work in composite mode and use a Paragraph for which you define the alignment.
The advantage of composite mode over text mode is that different paragraphs in the same cell can have different alignments, whereas you can only have one alignment in text mode. Another advantage is that you can add more than just text: you can also add images, lists, tables,... An advantage of text mode is speed: it takes less processing time to deal with the content of a cell.
private static PdfPCell PhraseCell(Phrase phrase, int align)
{
PdfPCell cell = new PdfPCell(phrase);
cell.BorderColor = BaseColor.WHITE;
// cell.VerticalAlignment = PdfCell.ALIGN_TOP;
//cell.VerticalAlignment = align;
cell.HorizontalAlignment = align;
cell.PaddingBottom = 2f;
cell.PaddingTop = 0f;
return cell;
}
Here is my derivation of user2660112's answer - one method to return a cell for insertion into a bordered and background-colored table, and a similar, but borderless/colorless variety:
private static PdfPCell GetCellForBorderedTable(Phrase phrase, int align, BaseColor color)
{
PdfPCell cell = new PdfPCell(phrase);
cell.HorizontalAlignment = align;
cell.PaddingBottom = 2f;
cell.PaddingTop = 0f;
cell.BackgroundColor = color;
cell.VerticalAlignment = PdfPCell.ALIGN_CENTER;
return cell;
}
private static PdfPCell GetCellForBorderlessTable(Phrase phrase, int align)
{
PdfPCell cell = new PdfPCell(phrase);
cell.HorizontalAlignment = align;
cell.PaddingBottom = 2f;
cell.PaddingTop = 0f;
cell.BorderWidth = PdfPCell.NO_BORDER;
cell.VerticalAlignment = PdfPCell.ALIGN_CENTER;
return cell;
}
These can then be called like so:
Font timesRoman9Font = FontFactory.GetFont(FontFactory.TIMES_ROMAN, 9, BaseColor.BLACK);
Font timesRoman9BoldFont = FontFactory.GetFont(FontFactory.TIMES_BOLD, 9, BaseColor.BLACK);
Phrase phrasesec1Heading = new Phrase("Duckbills Unlimited", timesRoman9BoldFont);
PdfPCell cellSec1Heading = GetCellForBorderedTable(phrasesec1Heading, Element.ALIGN_LEFT, BaseColor.YELLOW);
tblHeadings.AddCell(cellSec1Heading);
Phrase phrasePoisonToe = new Phrase("Poison Toe Toxicity Level (Metric Richter Scale, adjusted for follicle hue)", timesRoman9Font);
PdfPCell cellPoisonToe = GetCellForBorderlessTable(phrasePoisonToe, Element.ALIGN_LEFT);
tblFirstRow.AddCell(cellPoisonToe);
I ended up here searching for java Right aligning text in PdfPCell. So no offense if you are using java please use given snippet to achieve right alignment.
private PdfPCell getParagraphWithRightAlignCell(Paragraph paragraph) {
PdfPCell cell = new PdfPCell(paragraph);
cell.setBorderColor( BaseColor.WHITE);
cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
return cell;
}
In getParagraphWithRightAlignCell pass paragraph
Thanks
Perhaps its because you are mixing the different ways to add the cells? Have you tried explicitly creating a cell object, massaging it however you want then adding it for every cell?
Another thing you could try is setting the vertical alignment as well as the horizontal.
cell.HorizontalAlignment = Element.ALIGN_RIGHT;
Following the post made # POI Excel Merging Causing "Repaired Records: Format from /xl/styles.xml part (Styles)"
I have two excel files which are opening fine with styles and colors (In microsoft office 2010).
Iam merging both of those excel files using the code posted in the thread above.
The problem is with the styles (I created styles as below):
newCellStyle = newCell.getSheet().getWorkbook().createCellStyle();
newCellStyle.cloneStyleFrom(oldCellStyle);
styleMap.put(stHashCode, newCellStyle);
which has caused the styles problem "Repaired Records: Format from /xl/styles.xml part (Styles)"
after a fair amount of research what I learnt is the border and fill is causing the problem. Un setting these parameters has solved the problem. But as it states border and fill went missing.
Can some one throws idea around how to get the border and fill style from a cell and apply to a new cell ?
This appears to be a bug in Apache POI, #55800. The border ID and fill ID used in the "CoreXf" object aren't copied, causing the issue.
According to Comment 5 on that bug, it is possible to work around it by copying the fill and border attributes manually yourself.
The reason is it won't copy the XSSFCellFill and XSSFCellBorder. This also gives problem with borders. I have added a method in org.apache.poi.xssf.model.StylesTable which will help in creating a copy of workbook.
public void copyTo(StylesTable stylesTable){
stylesTable.numberFormats.clear();
stylesTable.fonts.clear();
stylesTable.fills.clear();
stylesTable.borders.clear();
stylesTable.styleXfs.clear();
stylesTable.xfs.clear();
stylesTable.dxfs.clear();
for(String str : numberFormats.values())
stylesTable.putNumberFormat(str);
for(XSSFFont font : fonts){
XSSFFont fontNew = new XSSFFont(font.getCTFont());
fontNew.registerTo(stylesTable);
}
for(XSSFCellFill fill : fills){
XSSFCellFill fillNew = new XSSFCellFill(fill.getCTFill());
stylesTable.putFill(fillNew);
}
for(XSSFCellBorder border : borders){
XSSFCellBorder borderNew = new XSSFCellBorder(border.getCTBorder());
stylesTable.putBorder(borderNew);
}
for(CTXf ctxf : styleXfs){
CTXf ctxfNew = (CTXf)ctxf.copy();
stylesTable.putCellStyleXf(ctxfNew);
}
for(CTXf ctxf : xfs){
CTXf ctxfNew = (CTXf)ctxf.copy();
stylesTable.putCellXf(ctxfNew);
}
for(CTDxf dxf : dxfs){
CTDxf dxfNew = (CTDxf)dxf.copy();
stylesTable.putDxf(dxfNew);
}
}
Following the post at https://issues.apache.org/bugzilla/show_bug.cgi?id=55800
As we are having trouble with border and fill
adding below piece of code worked like Charm
newCellStyle = newCell.getSheet().getWorkbook().createCellStyle();
newCellStyle.cloneStyleFrom(oldCellStyle);
// newCellStyle.getCoreXf().unsetBorderId();
// newCellStyle.getCoreXf().unsetFillId();
StylesTable newStylesSource = newCell.getSheet().getWorkbook().getStylesSource();
StylesTable oldStylesSource = oldCell.getSheet().getWorkbook().getStylesSource();
for (XSSFCellFill fill : oldStylesSource.getFills())
{
XSSFCellFill fillNew = new XSSFCellFill(fill.getCTFill());
newStylesSource.putFill(fillNew);
}
for (XSSFCellBorder border : oldStylesSource.getBorders())
{
XSSFCellBorder borderNew = new XSSFCellBorder(border.getCTBorder());
newStylesSource.putBorder(borderNew);
}
You could use the following code. I verified with .xlsx and I believe it would work with .xls also.
int stHashCode = oldCell.getCellStyle().hashCode();
CellStyle newCellStyle = newCell.getSheet().getWorkbook().createCellStyle();
newCellStyle.cloneStyleFrom(oldCell.getCellStyle());
newCell.setCellStyle(newCellStyle);
styleMap.put(stHashCode, newCellStyle);
if ( (newCell.getSheet().getWorkbook() instanceof XSSFWorkbook) && (oldCell.getSheet().getWorkbook() instanceof XSSFWorkbook) ){
StylesTable newStylesSource = ((XSSFWorkbook) newCell.getSheet().getWorkbook()).getStylesSource();
StylesTable oldStylesSource = ((XSSFWorkbook) oldCell.getSheet().getWorkbook()).getStylesSource();
for (XSSFCellFill fill : oldStylesSource.getFills()) {
XSSFCellFill fillNew = new XSSFCellFill(fill.getCTFill());
newStylesSource.putFill(fillNew);
}
for (XSSFCellBorder border : oldStylesSource.getBorders()) {
XSSFCellBorder borderNew = new XSSFCellBorder(border.getCTBorder());
newStylesSource.putBorder(borderNew);
}
}
I'm using iText 5.1.3, and I want to add a header to my Pdf Document. I used the known solution posted here: http://itextpdf.com/examples/iia.php?id=104
This solution used the PdfPageEventHelper class, and overridden the method onEndPage() to add the Header exactly after finishing every page. The example provided in the link above works fine as it adds a table as the Header of the document. I'm trying to do exactly the same with 1 difference, that I want some cells in that table to have Rowspan and/or Colspan.
I tried, and found that using table.writeSelectedRows() differs from document.add(table) when it comes to Rowspan. This is a sample of what I'm trying to do in onEndPage:
PdfPTable mytable = new PdfPTable(3);
mytable.setTotalWidth(527);
PdfPCell cell1 = new PdfPCell(new Phrase("Hello"));
cell1.setColspan(2);
cell1.setRowspan(2);
mytable.addCell(cell1);
PdfPCell cell2 = new PdfPCell(new Phrase("Girls !"));
mytable.addCell(cell2);
PdfPCell cell3 = new PdfPCell(new Phrase("Boys !"));
mytable.addCell(cell3);
mytable.writeSelectedRows(0, -1, 34, 803, writer.getDirectContent());
and instead of having a cell at the left as 2x2 with "Hello", I get the "Hello" cell as 1x2 not 2x2
Any ideas?
well .. I found the solution myself :D It's simply replacing mytable.writeSelectedRows(0, -1, 34, 803, writer.getDirectContent()); with the following:
ColumnText column = new ColumnText(writer.getDirectContent());
column.addElement(mytable);
column.setSimpleColumn(-12, -20, 604, 803); // set LLx, LLy, URx, and URy of the header
column.go();
That's it :) worked :)
iText writeSelectedRows not work with rowSpan when I use iText-2.1.7, The rowSpan cell not grow to other rows,But it has a workaround.
ArrayList tmp = table.getRows(0, table.getRows().size());
table.getRows().clear();
table.getRows().addAll(tmp);
table.writeSelectedRows(0, -1, x, y, directContent);
I use the following java code to successfully generate cell comments in Apache POI
public static void setComment(String text, Cell cell) {
final Map<Sheet, HSSFPatriarch> drawingPatriarches = new HashMap<Sheet, HSSFPatriarch>();
CreationHelper createHelper = cell.getSheet().getWorkbook().getCreationHelper();
HSSFSheet sheet = (HSSFSheet) cell.getSheet();
HSSFPatriarch drawingPatriarch = drawingPatriarches.get(sheet);
if (drawingPatriarch == null) {
drawingPatriarch = sheet.createDrawingPatriarch();
drawingPatriarches.put(sheet, drawingPatriarch);
}
Comment comment = drawingPatriarch.createComment(new HSSFClientAnchor(100, 100, 100, 100, (short)1, 1, (short) 10, 5));
comment.setString(createHelper.createRichTextString(text));
cell.setCellComment(comment);
}
I copied it from creating cell comments using HSSFClientAnchor in apache poi. Thank you Erik!
How can I change the size of the comment to 300 pixels width and 100 pixels height?
Thanks!
From what I can tell there's not an easy way since comment anchor points are specified by cell (column, row parameters) and offset into cell (dx, dy parameters). So you need to compute the width/height of the cells to figure out the second cell coordinates and then the offsets into that cell to make it exactly the pixel size you want.
Busy Developers' Guide to HSSF and XSSF Features
// When the comment box is visible, have it show in a 1x3 space
ClientAnchor anchor = factory.createClientAnchor();
anchor.setCol1(cell.getColumnIndex());
anchor.setCol2(cell.getColumnIndex()+1);
anchor.setRow1(row.getRowNum());
anchor.setRow2(row.getRowNum()+3);
Just change the values for setCol2 and setRow2.
You can assign a column width for any cell as follows:
sheet.setColumnWidth(0, 1000);