NPOI XWPF set table column width not working - apache-poi

I've been trying to set the column width for my table, but it won't budge. I'm using NPOI from this git https://github.com/nissl-lab/npoi.
Currently, my code is:
FileStream stream = new FileStream(reportPath, FileMode.Open);
XWPFDocument doc = new XWPFDocument(stream);
XWPFTable table;
table = doc.CreateTable(1, 3);
table.SetColumnWidth(0, (ulong)1000);
table.SetColumnWidth(1, (ulong)2000);
table.SetColumnWidth(2, (ulong)3000);
using (var f = File.Create(reportPath)) doc.Write(f);
And the generated columns are in the same size having the smallest column size possible. Also, I'm trying to generate a DOCX file.

You have to set the table width type to make it work.
XWPFTable table1 = doc.CreateTable(1, 3);
var tblLayout1 = table1.GetCTTbl().tblPr.AddNewTblLayout();
tblLayout1.type = ST_TblLayoutType.#fixed;
table1.SetColumnWidth(0, 1000);
table1.SetColumnWidth(1, 2000);
table1.SetColumnWidth(2, 3000);
The above code works in NPOI 2.5.4

Related

Apache FOP: PDF converted from POI HSSF (.xls) has no cell padding

I am creating HSSF Excel spreadsheet using Apache POI (version 5.2.3):
HSSFWorkbook workbook = new HSSFWorkbook();
CellStyle tableDefaultStyle = workbook.createCellStyle();
tableDefaultStyle.setBorderBottom(BorderStyle.THIN);
tableDefaultStyle.setBottomBorderColor(HSSFColor.HSSFColorPredefined.GREY_40_PERCENT.getIndex());
tableDefaultStyle.setBorderTop(BorderStyle.THIN);
tableDefaultStyle.setTopBorderColor(HSSFColor.HSSFColorPredefined.GREY_40_PERCENT.getIndex());
tableDefaultStyle.setBorderRight(BorderStyle.THIN);
tableDefaultStyle.setRightBorderColor(HSSFColor.HSSFColorPredefined.GREY_40_PERCENT.getIndex());
tableDefaultStyle.setBorderLeft(BorderStyle.THIN);
tableDefaultStyle.setLeftBorderColor(HSSFColor.HSSFColorPredefined.GREY_40_PERCENT.getIndex());
CellStyle rightAligned = workbook.createCellStyle();
rightAligned.cloneStyleFrom(tableDefaultStyle);
rightAligned.setAlignment(HorizontalAlignment.RIGHT);
CellStyle leftAligned = workbook.createCellStyle();
leftAligned.cloneStyleFrom(tableDefaultStyle);
leftAligned.setAlignment(HorizontalAlignment.LEFT);
Sheet sheet = workbook.createSheet();
Row row = sheet.createRow(0);
Cell cell_r = row.createCell(0);
cell_r.setCellStyle(rightAligned);
cell_r.setCellValue("right aligned");
sheet.setColumnWidth(0, 3000);
Cell cell_l = row.createCell(1);
cell_l.setCellStyle(leftAligned);
cell_l.setCellValue("left aligned");
sheet.setColumnWidth(1, 3000);
This is working fine:
Then I use ExcelToFoConverter to get a FO document:
Document foDocument = XMLHelper.getDocumentBuilderFactory().newDocumentBuilder().newDocument();
ExcelToFoConverter converter = new ExcelToFoConverter(foDocument);
converter.processWorkbook(workbook);
Finally I use Apache FOP to get PDF file:
FopFactory fopFactory = FopFactory.newInstance(new File(".").toURI());
Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, response.getOutputStream());
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer();
Source src = new DOMSource(foDocument);
Result res = new SAXResult(fop.getDefaultHandler());
transformer.transform(src, res);
The problem is that the resulting PDF file is hardly readable because rendered table cells have no padding:
According to the setColumnWidth documentation there are 2 pixels padding on both left and right side of each column, which seems to be just enough.
How to preserve padding in PDF? Or how to add padding in FO? Or how to make table in PDF more readable?

Export PDF file from Excel template with Qt and QAxObject

The project I am currently working on is to export an Excel file to PDF.
The Excel file is a "Template" that allows the generation of graphs. The goal is to fill some cells of the Excel file so that the graphs are generated and then to export the file in PDF.
I use Qt in C++ with the QAxObject class and all the data writing process works well but it's the PDF export part that doesn't.
The problem is that the generated PDF file also contains the data of the graphs while these data are not included in the print area of the Excel template.
The PDF export is done with the "ExportAsFixedFormat" function which has as a parameter the possibility to ignore the print area that is "IgnorePrintAreas" at position 5. Even if I decide to set this parameter to "false", so not to ignore the print area and therefore to take into account the print area, this does not solve the problem and it produces the same result as if this parameter was set to "true".
I tried to vary the other parameters, to change the type of data passed in parameter or not to use any parameter but it does not change anything to the obtained result which is always the same.
Here is the link to the "documentation" of the export command "ExportAsFixedFormat":
https://learn.microsoft.com/en-us/office/vba/api/excel.workbook.exportasfixedformat
I give you a simplified version of the command suite that is executed in the code:
Rapport::Rapport(QObject *parent) : QObject(parent)
{
//Create the template from excel file
QString pathTemplate = "/ReportTemplate_FR.xlsx"
QString pathReporter = "/Report"
this->path = QDir(QDir::currentPath() + pathReporter + pathTemplate);
QString pathAbsolute(this->path.absolutePath().replace("/", "\\\\"));
//Create the output pdf file path
fileName = QString("_" + QDateTime::currentDateTime().toString("yyyyMMdd-HHmmssff") + "_Report");
QString pathDocument = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation).append("/").replace("/", "\\\\");
QString exportName(pathDocument + fileName + ".pdf");
//Create the QAxObjet that is linked to the excel template
this->excel = new QAxObject("Excel.Application");
//Create the QAxObject « sheet » who can accepte measure data
QAxObject* workbooks = this->excel->querySubObject("Workbooks");
QAxObject* workbook = workbooks->querySubObject("Add(const QString&)", pathAbsolute);
QAxObject* sheets = workbook->querySubObject("Worksheets");
QAxObject* sheet = sheets->querySubObject("Item(int)", 3);
//Get some data measure to a list of Inner class Measurement
QList<Measurement*> actuMeasure = this->getSomeMeasure() ; //no need to know how it’s work…
//Create a 2 dimentional QVector to be able to place data on the table where we want (specific index)
QVector<QVector<QVariant>> vCells(actuMeasure.size());
for(int i = 0; i < vCells.size(); i++)
vCells[i].resize(6);
//Fill the 2 dimentional QVector with data measure
int row = 0;
foreach(Measurement* m, actuMeasure)
{
vCells[row][0] = QVariant(m->x);
vCells[row][1] = QVariant(m->y1);
vCells[row][2] = QVariant(m->y2);
vCells[row][3] = QVariant(m->y3);
vCells[row][4] = QVariant(m->y4);
vCells[row][5] = QVariant(m->y5);
row++;
}
//Transform the 2 dimentional QVector on a QVariant object
QVector<QVariant> vvars;
QVariant var;
for(int i = 0; i < actuMeasure.size(); i++)
vvars.append(QVariant(vCells[i].toList()));
var = QVariant(vvars.toList());
//Set the QVariant object that is the data measure on the excel file
sheet->querySubObject("Range(QString)", "M2:AB501")->setProperty("Value", var);
//Set the fileName on the page setup (not relevant for this example)
sheet->querySubObject("PageSetup")->setProperty("LeftFooter", QVariant(fileName));
//Export to PDF file with options – NOT WORKING !!!
workbook->dynamicCall("ExportAsFixedFormat(const QVariant&, const QVariant&, const QVariant&, const QVariant&, const QVariant&)", QVariant(0), QVariant(exportName), QVariant(0), QVariant(false), QVariant(false));
//Close
workbooks->dynamicCall("Close()");
this->excel->dynamicCall("Quit()");
}
A this point I really need help to find a way to solve this problem.
I also wonder if this is not a bug of the QAxObject class.
I finally found a solution on another forum.
If anyone needs help, I'll leave the link to the answer.

EPPlus - How to add "Series Lines" in Pivot Chart (ColumnStacked)

I am using EPPlus library to generate pivot chart in excel.
I created the chart but don't know how I can add "Series Lines" to it.
The arrow in the below image indicates series lines.
Chart - Series Lines
Here is the sample code.
var wsBar = pck.Workbook.Worksheets.Add("Bar");
--dataRange = Data from "Data" worksheet.
var pivotTable1 = wsBar.PivotTables.Add(wsBar.Cells["Z100"], dataRange, "pivotTable1");
var dataFieldBar1 = pivotTable1.DataFields.Add(pivotTable1.Fields[22]);
dataFieldBar1.Format = "$ #,###.00";
pivotTable1.DataOnRows = true;
pivotTable1.RowFields.Add(pivotTable1.Fields[15]);
pivotTable1.ColumnFields.Add(pivotTable1.Fields[12]);
pivotTable1.PageFields.Add(pivotTable1.Fields[7]);
var columnchart = wsBar.Drawings.AddChart("ColumnChart", eChartType.ColumnStacked, pivotTable1);
columnchart.SetPosition(0, 0, 0, 0);
columnchart.SetSize(600, 300);
Any help is highly appreciated.
Dont think EPPlus has that as an option so it would be some kind of XML manipulation without another library:
var chartXml = columnchart.ChartXml;
var nsm = new XmlNamespaceManager(chartXml.NameTable);
var nsuri = chartXml.DocumentElement.NamespaceURI;
nsm.AddNamespace("c", nsuri);
var serNode = chartXml.SelectSingleNode("c:chartSpace/c:chart/c:plotArea/c:barChart", nsm);
var serLinesNode = chartXml.CreateNode(XmlNodeType.Element, "serLines", nsuri);
serNode.AppendChild(serLinesNode);

Make an Entire Cell in a MigraDoc Table a Link

Is there a way in MigraDoc to make an entire table cell a link? I have a tabular table of contents, and the page number is difficult to click. I would prefer if the entire cell was clickable to navigate to a specified page. Here is an example of my code:
// Create the table within the document
var document = new Document();
var section = document.AddSection();
var table = section.AddTable();
// Create a column in the table
var column = table.AddColumn();
column.Width = "2cm";
// Create a row in the table
var row = table.AddRow();
row.Height = "1cm";
// Add a hyperlink to the appropriate page
var paragraph = row.Cells[0].AddParagraph();
var hyperlink = paragraph.AddHyperlink("MyBookmarkName");
hyperlink.AddPageRefField("MyBookmarkName");
...
// Create the bookmark later in the document
I'm afraid there is no easy way to make the whole cell clickable. I haven't tried it myself, but you can add images (visible or transparent) or text to the hyperlink.
This will make the clickable area bigger - and if you use e.g. blue underlined text there will be a visual hint that the text is clickable.
I was inspired by the answer from the PDFsharp Team to try and fill the cell with a blank hyperlink image, with text over the hyperlink. Since my ultimate goal was to actually make an entire row a hyperlink, I came up with the following solution.
First, add an additional zero-width column prior to the first column in the table that you want to be a hyperlink. Next, add a paragraph, hyperlink, and transparent 1-pixel image to each zero-width cell. Specify the image height and width to fill however many table cells you want to be a link. Also, be sure to set the font size of the paragraph containing the link to nearly zero (zero throws an exception, but images are aligned on the font baseline, so you need a very small number to prevent the paragraph from being larger than the image).
Note that a zero-width column, even with borders, does not change the apparent border width when viewing the resulting PDF. The following code illustrates my approach:
// Declare some constants
var _rowHeight = new Unit(.75, UnitType.Centimeter);
// Create the document, section, and table
var document = new Document();
var section = document.AddSection();
var table = section.AddTable();
// Format the table
table.Rows.Height = _rowHeight;
table.Rows.VerticalAlignment = VerticalAlignment.Center;
// Define the column titles and widths
var columnInfos = new[] {
new { Title = "Non-Link Column", Width = new Unit(8, UnitType.Centimeter) },
new { Title = "" , Width = new Unit(0 ) },
new { Title = "Link Column 1" , Width = new Unit(8, UnitType.Centimeter) },
new { Title = "Link Column 2" , Width = new Unit(8, UnitType.Centimeter) },
};
// Define the column indices
const int colNonLink = 0;
const int colHyperlink = 1;
const int colLink1 = 2;
const int colLink2 = 3;
// Create all of the table columns
Unit tableWidth = 0;
foreach (var columnInfo in columnInfos)
{
table.AddColumn(columnInfo.Width);
tableWidth += columnInfo.Width;
}
// Remove the padding on the link column
var linkColumn = table.Columns[colHyperlink];
linkColumn.LeftPadding = 0;
linkColumn.RightPadding = 0;
// Compute the width of the summary links
var linkWidth = tableWidth -
columnInfos.Take(colHyperlink).Sum(ci => ci.Width);
// Create a row to store the column headers
var headerRow = table.AddRow();
headerRow.Height = ".6cm";
headerRow.HeadingFormat = true;
headerRow.Format.Font.Bold = true;
// Populate the header row
for (var colIdx = 0; colIdx < columnInfos.Length; ++colIdx)
{
var columnTitle = columnInfos[colIdx].Title;
if (!string.IsNullOrWhiteSpace(columnTitle))
{
headerRow.Cells[colIdx].AddParagraph(columnTitle);
}
}
// In the real code, the following is done in a loop to dynamically add rows
var row = table.AddRow();
// Populate the row header
row.Cells[colNonLink].AddParagraph("Not part of link");
// Change the alignment of the link cell
var linkCell = row.Cells[colHyperlink];
linkCell.VerticalAlignment = VerticalAlignment.Top;
// Add a hyperlink that fills the remaining cells in the row
var linkParagraph = linkCell.AddParagraph();
linkParagraph.Format.Font.Size = new Unit(.001, UnitType.Point);
var hyperlink = linkParagraph.AddHyperlink("MyBookmarkName");
var linkImage = hyperlink.AddImage("Transparent.gif");
linkImage.Height = _rowHeight;
linkImage.Width = linkWidth;
// Populate the remaining two cells
row.Cells[colLink1].AddParagraph("Part of link 1");
row.Cells[colLink2].AddParagraph("Part of link 2");
// Add a border around the cells
table.SetEdge(0, 0, columnInfos.Length, table.Rows.Count,
Edge.Box | Edge.Interior, BorderStyle.Single, .75, Colors.Black);
The result of the above code is a document containing a table with 2 rows, 3 visible columns, where the entirety of the last two cells in the final row are a hyperlink to "MyBookmarkName". Just for reference, I did modify the PDFSharp source code according to the advice here to remove borders around hyperlinks, which looked wonky at certain zoom levels in Adobe Acrobat Reader.

Aspose Slides Table Cell Insert HTML content

I am working with Aspose slides to generate PPT in my application, I ran into a situation where I need to insert HTML text into Table Cell, I verified all blogs no one given answer to me. If any body know here please let me know. Thanks In advance.
You can use the TextFrame's paragraph associated with each cell to insert HTML using Aspose.Slides for .NET. Check the following code:
//Instantiate Presentation class that represents PPTX file
using (Presentation pres = new Presentation())
{
//Access first slide
ISlide sld = pres.Slides[0];
//Define columns with widths and rows with heights
double[] dblCols = { 250, 250};
double[] dblRows = { 150, 130, 130 };
//Add table shape to slide
ITable tbl = sld.Shapes.AddTable(100, 50, dblCols, dblRows);
//Set border format for each cell
foreach (IRow row in tbl.Rows)
foreach (ICell cell in row)
{
cell.BorderTop.FillFormat.FillType = FillType.Solid;
cell.BorderTop.FillFormat.SolidFillColor.Color = Color.Red;
cell.BorderTop.Width = 5;
cell.BorderBottom.FillFormat.FillType = FillType.Solid;
cell.BorderBottom.FillFormat.SolidFillColor.Color = Color.Red;
cell.BorderBottom.Width = 5;
cell.BorderLeft.FillFormat.FillType = FillType.Solid;
cell.BorderLeft.FillFormat.SolidFillColor.Color = Color.Red;
cell.BorderLeft.Width = 5;
cell.BorderRight.FillFormat.FillType = FillType.Solid;
cell.BorderRight.FillFormat.SolidFillColor.Color = Color.Red;
cell.BorderRight.Width = 5;
}
//Adding html text in text frame
tbl[0, 0].TextFrame.Paragraphs.AddFromHtml(#"<html><body><p><b>This text is bold</b></p>
<p><i>This text is italic</i></p><p>This is<sub> subscript</sub> and <sup>superscript</sup></p>
</body></html>");
//Write PPTX to Disk
pres.Save("d:\\data\\table_html.pptx", Aspose.Slides.Export.SaveFormat.Pptx);
}
P.S. I am working as social media developer at Aspose.

Resources