Converting short colorVal = CellStyle.getBottomBorderColor () to RGB value while using Apache POI Java library - itext

I am reading Excel sheet using Apache POI and writing it to a PDF using iText library.This has been achieved successfully but I am getting default black border for every cell that I write to PDF. So I need to get the cell border color using Apache POI which can be achieved using CellStyle class method getBottomBorderColor() which returns a short value.However I need a way to convert this value to RGB value so that while writing cell to PDF I can apply that RGB color value to the cell border.

The short value from CellStyle.getBottomBorderColor is an index of the color in the color palette of the workbook. This is an olld approach for storing colors from the old binary *.xls Excel format. So in apache poi there is only HSSFPalette which only should be used in HSSF and not more be used in XSSF.
In newer *.xlsx Excel formats, the color will either be stored directly as hex value or as reference to a theme color. So for XSSF there is XSSFCellStyle.getBottomBorderXSSFColor to get that color directly and not via index.
So unfortunately we have to differ both aproaches dependent on the kind of Excel workbook.
Example:
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor;
import java.io.FileInputStream;
class ExcelCellBorderColor{
public static void main(String[] args) throws Exception {
Workbook wb = WorkbookFactory.create(new FileInputStream("ExcelCellBorderColor.xlsx"));
//Workbook wb = WorkbookFactory.create(new FileInputStream("ExcelCellBorderColor.xls"));
String strrgb;
Sheet sheet = wb.getSheetAt(0);
for (Row row : sheet) {
for (Cell cell : row) {
CellStyle style = cell.getCellStyle();
if (style instanceof XSSFCellStyle) {
XSSFColor xssfcolor = ((XSSFCellStyle)style).getBottomBorderXSSFColor();
if (xssfcolor != null) {
byte[] brgb = xssfcolor .getRGB();
strrgb = "R:"+String.format("%02X", brgb[0])+",G:"+String.format("%02X", brgb[1])+",B:"+String.format("%02X", brgb[2]);
System.out.println("Cell " + cell.getAddress() + " has border bottom color: " + strrgb);
}
} else if (style instanceof HSSFCellStyle) {
short colorindex = ((HSSFCellStyle)style).getBottomBorderColor();
HSSFPalette palette = ((HSSFWorkbook)wb).getCustomPalette();
HSSFColor hssfcolor = palette.getColor(colorindex);
if (hssfcolor != null) {
short[] srgb = hssfcolor.getTriplet();
strrgb = "R:"+String.format("%02X", srgb[0])+",G:"+String.format("%02X", srgb[1])+",B:"+String.format("%02X", srgb[2]);
System.out.println("Cell " + cell.getAddress() + " has border bottom color index: " + colorindex + ". This is " + strrgb);
}
}
}
}
wb.close();
}
}

you can archive this by using this color class
CTScRgbColor scrgb = (CTScRgbColor)ch;
int r = scrgb.getR();
int g = scrgb.getG();
int b = scrgb.getB();
color = new Color(255 * r / 100000, 255 * g / 100000, 255 * b / 100000);

Related

ChartJS: Custom tooltip always displaying

Im using ChartJS to create a graph on my website.
Im trying to create a custom tooltip. According to the documentation, this should be easy:
var myPieChart = new Chart(ctx, {
type: 'pie',
data: data,
options: {
tooltips: {
custom: function(tooltip) {
// tooltip will be false if tooltip is not visible or should be hidden
if (!tooltip) {
return;
}
}
}
}
});
My problem is that the tooptip is never false and because of this my custom tooltip is always displayed.
Please see this JSFiddle (line 42 is never executed)
Question: Is it a bug that tooltip is never false, or am I missing something?
The custom tooltip option is used for when you want to create/style your own tooltip using HTLM/CSS outside of the scope of the canvas (and not use the built in tooltips at all).
In order to do this, you must define a place outside of your canvas to contain your tooltip (e.g. a div) and then use that container within your tooltips.custom function.
Here is an example where I used a custom tooltip to display the hovered pie chart section percentage in the middle of the chart. In this example I'm generating my tooltip inside a div with id "chartjs-tooltip". Notice how I interact with this div in my tooltips.custom function to position and change the value.
Also, the correct way to check if the tooltip should be hidden is to check it's opacity. The tooltip object will always exist, but when it should not be visible, the opacity is set to 0.
Chart.defaults.global.tooltips.custom = function(tooltip) {
// Tooltip Element
var tooltipEl = document.getElementById('chartjs-tooltip');
// Hide if no tooltip
if (tooltip.opacity === 0) {
tooltipEl.style.opacity = 0;
return;
}
// Set Text
if (tooltip.body) {
var total = 0;
// get the value of the datapoint
var value = this._data.datasets[tooltip.dataPoints[0].datasetIndex].data[tooltip.dataPoints[0].index].toLocaleString();
// calculate value of all datapoints
this._data.datasets[tooltip.dataPoints[0].datasetIndex].data.forEach(function(e) {
total += e;
});
// calculate percentage and set tooltip value
tooltipEl.innerHTML = '<h1>' + (value / total * 100) + '%</h1>';
}
// calculate position of tooltip
var centerX = (this._chartInstance.chartArea.left + this._chartInstance.chartArea.right) / 2;
var centerY = ((this._chartInstance.chartArea.top + this._chartInstance.chartArea.bottom) / 2);
// Display, position, and set styles for font
tooltipEl.style.opacity = 1;
tooltipEl.style.left = centerX + 'px';
tooltipEl.style.top = centerY + 'px';
tooltipEl.style.fontFamily = tooltip._fontFamily;
tooltipEl.style.fontSize = tooltip.fontSize;
tooltipEl.style.fontStyle = tooltip._fontStyle;
tooltipEl.style.padding = tooltip.yPadding + 'px ' + tooltip.xPadding + 'px';
};
Here is the full codepen example.
I hope that helps clear things up!

zxing Datamatrix generator creating rectangular barcode which can't be scanned

I am using barcodewriter to write datamatrix barcoe. While most of the times it creates correct square style datamatrix barcode, for some of text it creates rectangular shaped barcode.
For inputData like below it creates rectangular barcode
8004600000070000017
C/TH PAUL PENGELLY
C/TH NICKY PARSONS
C/TH ROSEMARIE BARTOLOME
while for others it creates square styled: CTH HEKT-WOODROW MORGAN
800460000007
800460000007000001700000
i am usinf this code to generate code:
BarcodeWriter writer = new BarcodeWriter() { Format = BarcodeFormat.DATA_MATRIX };
var img = writer.Write(inputData);
return new Bitmap(img);
img.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
dto.BarcodeImage = ms.ToArray();
How can I make sure that I always get Square shaped datamatrix?
I have alread tried adding height,width options.
Thanks
There is SymbolShape option which can be used to force shape .
DatamatrixEncodingOptions options = new DatamatrixEncodingOptions()
{
Height = 300,
Width = 300,
PureBarcode = true,
Margin = 1,
SymbolShape = SymbolShapeHint.FORCE_SQUARE
};
It is not easy to detect but after careful reviewing, I found how to do it.
readonly DataMatrixWriter DMencoder = new();
readonly Dictionary<EncodeHintType, object> DMencodeType = new()
{
[EncodeHintType.DATA_MATRIX_DEFAULT_ENCODATION] = Encodation.C40, //Optional
[EncodeHintType.DATA_MATRIX_SHAPE] = SymbolShapeHint.FORCE_SQUARE
};
DMencoder.encode(matrixText, BarcodeFormat.DATA_MATRIX, 100, 100, DMencodeType)

Mixing text and images causes incorrect vertical positioning

Using iTextSharp version 5.5.8 (same bug existed in 5.5.7), there's an unpleasant bug when you add images to Chapters and Sections - the images and the section headings start out OK but quickly become offset relative to each other.
The PDF generated from the following code starts out correctly, it says "Section 1" and below it is the image. The next section ("Section 2") has a little of the image overlapping the section text, the next section is even worse, etc. I think it's the text that's mal-positioned, not the image.
Is this a known iTextSharp bug?
static Document m_doc = null;
static BaseFont m_helvetica = null;
static Font m_font = null;
static PdfWriter m_writer = null;
static Image m_image = null;
static void Main(string[] args)
{
m_doc = new Document(PageSize.LETTER);
m_helvetica = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
m_font = new Font(m_helvetica, 10.0f);
m_writer = PdfWriter.GetInstance(m_doc, new FileStream("Output.pdf", FileMode.Create));
m_writer.StrictImageSequence = true;
m_doc.Open();
m_doc.Add(new Chunk("Created by iTextSharp version " + new iTextSharp.text.Version().GetVersion, m_font));
Chapter chapter = new Chapter("Chapter 1", 1);
chapter.TriggerNewPage = false;
if (m_image == null)
{
m_image = Image.GetInstance(new Uri("https://pbs.twimg.com/profile_images/2002307628/Captura_de_pantalla_2012-03-17_a_la_s__22.14.48.png"));
m_image.ScaleAbsolute(100, 100);
}
for (int i = 0; i < 5; i++)
{
Section section = chapter.AddSection(18, "Section " + (i + 1));
section.Add(new Chunk(" ", m_font));
section.Add(m_image);
}
m_doc.Add(chapter);
m_doc.Close();
}
From the documentation for the Java version:
A Section is a part of a Document containing other Sections, Paragraphs, List and/or Tables.
Further looking at the Add() method in the C# source we see:
Adds a Paragraph, List, Table or another Section
Basically, instead of a Chunk use a Paragraph. So instead of this
section.Add(new Chunk(" ", m_font));
Use this:
section.Add(new Paragraph(new Chunk(" ", m_font)));
Or even just this:
section.Add(new Paragraph(" ", m_font));

How do I change the weight of a simulated bold font using itext

I am using the iText library to generate text. I am loading the Arial Unicode MS font which does not contain a bold style so iText is simulating the bold. This works fine, but the weight of the bold font appears too heavy compared with text generated using the Java API or even using Microsoft Word.
I tried to get the weight from the FontDescriptor, but the value returned is always 0.0
float weight = font.getBaseFont().getFontDescriptor(BaseFont.FONT_WEIGHT, fontSize);
Is there a way I can change the weight of a simulated bold font?
As an addendum to #Chris' answer: You do not need to construct those Object[]s as there is a Chunk convenience method:
BaseFont arialUnicodeMs = BaseFont.createFont("c:\\Windows\\Fonts\\ARIALUNI.TTF", BaseFont.WINANSI, BaseFont.EMBEDDED);
Font arial12 = new Font(arialUnicodeMs, 12);
Paragraph p = new Paragraph();
for (int i = 1; i < 100; i++)
{
Chunk chunk = new Chunk(String.valueOf(i) + " ", arial12);
chunk.setTextRenderMode(PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE, i/100f, null);
p.add(chunk);
}
document.add(p);
results in
EDIT
Sorry, I just realized after posting this that you're using iText but my answer is for iTextSharp. You should, however, be able to use most of the code below. I've updated the source code link to reference the appropriate Java source.
Bold simulation (faux bold) is done by drawing the text with a stroke. When iText is asked to draw bold text with a non-bold font it defaults to applying a stroke with a width of of the font's size divided by 30. You can see this in the current source code here. The magic part is setting the chunk's text rendering mode to a stroke of your choice:
//.Net code
myChunk.Attributes[Chunk.TEXTRENDERMODE] = new Object[] { PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE, MAGIC_NUMBER_HERE, null };
//Java code
myChunk.attributes.put(Chunk.TEXTRENDERMODE, new Object[]{Integer.valueOf(PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE), MAGIC_NUMBER_HERE, null});
Knowing that you can just apply the same logic but using your weight preference. The sample below creates four chunks, the first normal, the second faux-bold, the third ultra-heavy faux-bold and the fourth ultra-lite faux-bold.
//.Net code below but should be fairly easy to convert to Java
//Path to our PDF
var testFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "test.pdf");
//Path to our font
var ff = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Fonts), "ARIALUNI.TTF");
//Normal document setup, nothing special here
using (var fs = new FileStream(testFile, FileMode.Create, FileAccess.Write, FileShare.None)) {
using (var doc = new Document()) {
using (var writer = PdfWriter.GetInstance(doc, fs)) {
doc.Open();
//Register our font
FontFactory.Register(ff, "Arial Unicode MS");
//Declare a size to use throughout the demo
var size = 20;
//Get a normal and a faux-bold version of the font
var f = FontFactory.GetFont("Arial Unicode MS", BaseFont.IDENTITY_H, BaseFont.EMBEDDED, size, iTextSharp.text.Font.NORMAL);
var fb = FontFactory.GetFont("Arial Unicode MS", BaseFont.IDENTITY_H, BaseFont.EMBEDDED, size, iTextSharp.text.Font.BOLD);
//Create a normal chunk
var cNormal = new Chunk("Hello ", f);
//Create a faux-bold chunk
var cFauxBold = new Chunk("Hello ", fb);
//Create an ultra heavy faux-bold
var cHeavy = new Chunk("Hello ", f);
cHeavy.Attributes = new Dictionary<string, object>();
cHeavy.Attributes[Chunk.TEXTRENDERMODE] = new Object[] { PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE, size / 10f, null };
//Create a lite faux-bold
var cLite = new Chunk("Hello ", f);
cLite.Attributes = new Dictionary<string, object>();
cLite.Attributes[Chunk.TEXTRENDERMODE] = new Object[] { PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE, size / 50f, null };
//Add to document
var p = new Paragraph();
p.Add(cNormal);
p.Add(cFauxBold);
p.Add(cHeavy);
p.Add(cLite);
doc.Add(p);
doc.Close();
}
}
}

Extjs quicktip display empty box

I am trying to implement a tool tip (QuickTip) functionality on a GXT grid cell.It seems to work most of the time, but some times I get an empty tooltip box while mousing over the column header. I found some articles stating the tooltip is only applicable to the data and not on header,but thats not the case I guess. I made the toolTip/text null by default, still I see empty box on header-mouse over.Am I doing something wrong?
This is my code:
ColumnConfig columnTitle = new ColumnConfig();
columnTitle.setId("subject");
columnTitle.setHeader("<B>Title</B>")
columnTitle.setRenderer(new GridCellRenderer<ModelData>()
{
#Override
public Object render(ModelData model, String property, ColumnData config, int rowIndex, int colIndex,
ListStore<ModelData> store, Grid<ModelData> grid)
{
SystemUserMessage msg = ((BeanModel)model).getBean();
String text = null;
text = msg.getSubject();
String content = model.get("content").toString();
String toolTip = null;
toolTip = " qtip='" + content + "'";
String style = null;
if(msg.getPriority().equals("High"))
{
style = " style='color: red;'";
}
String html = "<span" + toolTip + style + ">" + text + "</span>";
return html;
}
});
new QuickTip(messageCenterGrid); //register the tooltip
Try replacing qtip= with data-qtip= . You can also add data-qtitle=
Edit helpful link per Juan : http://docs.sencha.com/ext-js/4-1/#!/api/Ext.tip.QuickTipManager