Itext7 not showing arabic text - c#

I am trying to create a Pdf document using IText7. Despite the table looks as expected, just found a big problem, this does not show Arabic letters.
I've tried adding new fonts and changing the encoding.
I'm displaying Arabic letters in the wrong direction and they are separated, changing the base direction from right to left didn't help.
This is the part of the code:
string font = "naskh.ttf";
PdfFontFactory.Register(font);
FontProgram fontProgram = FontProgramFactory.CreateFont(font, true);
PdfFont f = PdfFontFactory.CreateFont(font,true);
Cell cell = new Cell(1, 3)
.Add(new Paragraph(" English عربي "))
.SetFont(f).SetFontScript(UnicodeScript.ARABIC)
.SetFontSize(33).SetBaseDirection(BaseDirection.RIGHT_TO_LEFT)
.SetFontColor(DeviceGray.WHITE)
.SetBackgroundColor(new DeviceRgb(80, 140, 80))
.SetTextAlignment(TextAlignment.CENTER);
The result is like this:
I've tried everything I could find online, lots of them are java or older version, I tried to change them to work on c# Itext7 but still no result
the closest I cot was with PdfFont f = PdfFontFactory.CreateFont(alaw, "Identity-H", true);
where I got 3 letters in the wrong order
I even tried to use \u0644\u0648\u0631\u0627\u0646\u0633 \u0627\u0644\u0639\u0631\u0628 (copied from an answer as string, but still not shown.
I can't use paid add-ons
Any solution to be able to write Arabic?

add language Processor:
LanguageProcessor languageProcessor = new ArabicLigaturizer();
and modify cell or PdfDocument like that:
com.itextpdf.kernel.pdf.PdfDocument tempPdfDoc = new com.itextpdf.kernel.pdf.PdfDocument(new PdfReader(pdfFile.getPath()), TempWriter);
com.itextpdf.layout.Document TempDoc = new com.itextpdf.layout.Document(tempPdfDoc);
com.itextpdf.layout.element.Paragraph paragraph0 = new com.itextpdf.layout.element.Paragraph(languageProcessor.process("الاستماره الالكترونية--الاستماره الالكترونية--الاستماره الالكترونية--الاستماره الالكترونية"))
.setFont(f).setBaseDirection(BaseDirection.RIGHT_TO_LEFT)
.setFontSize(15);
the final will be something like :
String font = "your Arabic font";
PdfFontFactory.register(font);
FontProgram fontProgram = FontProgramFactory.createFont(font, true);
PdfFont f = PdfFontFactory.createFont(fontProgram, PdfEncodings.IDENTITY_H);
LanguageProcessor languageProcessor = new ArabicLigaturizer();
com.itextpdf.kernel.pdf.PdfDocument tempPdfDoc = new
com.itextpdf.kernel.pdf.PdfDocument(new PdfReader(pdfFile.getPath()), TempWriter);
com.itextpdf.layout.Document TempDoc = new
com.itextpdf.layout.Document(tempPdfDoc);
com.itextpdf.layout.element.Paragraph paragraph0 = new
com.itextpdf.layout.element.Paragraph(languageProcessor.process("الاستماره الالكترونية--الاستماره الالكترونية--الاستماره الالكترونية--الاستماره الالكترونية"))
.setFont(f).setBaseDirection(BaseDirection.RIGHT_TO_LEFT)
.setFontSize(15);
//and look how i useded setBaseDirection & and don't use TextAlignment ,it will work without it

Related

Gembox document removes table of contents

I'm using Gembox document to replace some text in a docx document and it works great. However, I have a table of contents field that disappears after saving the document.
I tried doing the following but the field still disappears leaving only the placeholder text:
var toc = (TableOfEntries)document.GetChildElements(true, ElementType.TableOfEntries).First();
toc.Update();
document.GetPaginator(new PaginatorOptions() { UpdateFields = true });
UPDATE (2021-01-15):
Please try again with the latest version from the BugFixes page or from NuGet.
The latest version will work on the machine that uses culture with ';' character as a list separator.
Or you can specify that culture like this:
var toc = (TableOfEntries)document.GetChildElements(true, ElementType.TableOfEntries).First();
CultureInfo.CurrentCulture = new CultureInfo("fr");
toc.Update();
document.GetPaginator(new PaginatorOptions() { UpdateFields = true });
Also, the issue with the missing tab stop should be resolved now as well.
ORIGINAL:
When I tried to update your TOC from MS Word, I got the following:
No table of contents entries found.
After investigating the field's code of your TOC element, I figured out what the problem is.
This is the instruction text that you have:
{ TOC \h \z \t "TitreChapitre;1;SousTitreChapitre;2" }
These semicolon character separators (;) are culture-dependent. In other words, updating this TOC element will work on a machine that has a French region and settings, but it won't work when you have an English region and settings.
I'm currently on vacation, so I can't do anything about this. When I come back I will fix this problem for you.
For now, can you use the following as a workaround (I also noticed an issue with missing TabStop, this workaround will cover that as well):
var toc = (TableOfEntries)document.GetChildElements(true, ElementType.TableOfEntries).First();
var section = toc.Parent as Section;
var tocWidth = section.PageSetup.PageWidth - section.PageSetup.PageMargins.Left - section.PageSetup.PageMargins.Right;
var toc1Style = document.Styles["toc 1"] as ParagraphStyle;
var toc1TabStop = new TabStop(tocWidth - toc1Style.ParagraphFormat.RightIndentation, TabStopAlignment.Right, TabStopLeader.Dot);
toc1Style.ParagraphFormat.Tabs.Add(toc1TabStop);
var toc2Style = document.Styles["toc 2"] as ParagraphStyle;
var toc2TabStop = new TabStop(tocWidth - toc2Style.ParagraphFormat.RightIndentation, TabStopAlignment.Right, TabStopLeader.Dot);
toc2Style.ParagraphFormat.Tabs.Add(toc2TabStop);
toc.InstructionText = toc.InstructionText.Replace(';', ',');
toc.Update();
document.GetPaginator(new PaginatorOptions() { UpdateFields = true });
I hope this works for you.

How to remove paragraph spacing in output using the Microsoft.Office.Interop.Word Library

In my C# Desktop app i am using the Microsoft.Office.Interop.Word library to write to a word file. But whenever its done exporting there's huge spaces between paragraphs. Using the paragraph1.Range.ParagraphFormat.SpaceAfter = 0; parameter doesn't affect the result as well.
My desired result is the "No Spacing" preset in Word but after some research i found out it is not an option this library.
Is there any way to remove or set the spacing between paragraphs.
This is my code:
Microsoft.Office.Interop.Word.Application word = new Application();
word.Visible = false;
var doc = word.Documents.Add();
var paragraph1 = doc.Content.Paragraphs.Add();
paragraph1.Range.Font.Name = "Calibri";
paragraph1.Range.Font.Size = 11;
paragraph1.Range.ParagraphFormat.SpaceBefore = 0;
paragraph1.Range.ParagraphFormat.SpaceAfter = 0;
paragraph1.Range.Text = story;
paragraph1.Range.InsertParagraphAfter();
doc.SaveAs2(#"F:\Documents\Visual Studio Projects\LITPC\LITPC\bin\Debug\"+title+".docx");
word.Quit();
First of all the SpaceBefore and SpaceAfter properties take floats so you need to suffix your values with an f.
Try: paragraph1.SpaceBefore = 0.0f;, that worked for me.
Also, be careful to reset the spacing when you insert a new paragraph because subsequent paragraphs will inherit the new spacing.
Or avoid Interop Word altogether if you can, it's a deep, dark, rabbit hole I've been down for several days.
I solved this problem by changing the Word.Paragraph.SpaceAfter parameter on previous paragraph. For example.
// First Paragraph
Word.Paragraph mainTitle = document.Paragraphs.Add();
mainTitle.Range.Text = "para1";
mainTitle.Alignment = Word.WdParagraphAlignment.wdAlignParagraphCenter;
mainTitle.Range.InsertParagraphAfter();
mainTitle.SpaceAfter = 0.0f;
// Second Paragraph
Word.Paragraph semiTitle = document.Paragraphs.Add();
semiTitle.Range.Text = "para2";
semiTitle.Alignment = Word.WdParagraphAlignment.wdAlignParagraphCenter;
semiTitle.Range.InsertParagraphAfter();
semiTitle.SpaceAfter = 10.0f;
So, the SpaceAfter of semiTitle will be 0. Similarly, the SpaceAfter of the next paragraph after semiTitle will be 10.

NPOI Excel / C# Need formula to programatically change background for conditional formatting

I'm using NPOI to programatically create an Excel file. One of the requirements is that it needs to be able to change the background of cells based on values - green for good numbers, red for bad, etc. I have everything working perfectly and can create formulas...but I cannot for the life of me find a formula that shows how to change background color. No matter how I try to google for the answer, everything just wants to show how to open Excel and use the conditional formatting wizard. I'm overlooking something? Is there a way I can see the formula that the conditional formatting wizard created and just copy and paste it into my code?
Below is a sample I set up to change the field to Pass/Fail...but my peeps like shiny colors to go along with it...
XSSFWorkbook wb = new XSSFWorkbook();
XSSFSheet sh = (XSSFSheet)wb.CreateSheet("ACT");
string cf = "IF(" + engCell + (detailRow.RowNum + 1) + #">17,""Pass :)"", ""Fail :("")";
detailRow.CreateCell(detailIdx);
detailRow.GetCell(detailIdx).SetCellType(CellType.Formula);
detailRow.GetCell(detailIdx++).SetCellFormula(cf);
I figured it out!!! I hope this may help others who are using NPOI XSSF for conditional formatting:
XSSFWorkbook wb = new XSSFWorkbook();
XSSFSheet sh = (XSSFSheet)wb.CreateSheet("ACT");
sh.CreateRow(0).CreateCell(0).SetCellValue(14);
sh.CreateRow(1).CreateCell(0).SetCellValue(20);
sh.CreateRow(2).CreateCell(0).SetCellValue(10);
sh.CreateRow(3).CreateCell(0).SetCellValue(23);
sh.CreateRow(4).CreateCell(0).SetCellValue(19);
sh.CreateRow(5).CreateCell(0).SetCellValue(14);
XSSFSheetConditionalFormatting sCF = (XSSFSheetConditionalFormatting)sh.SheetConditionalFormatting;
//Fill Green if Passing Score
XSSFConditionalFormattingRule cfGreen =
(XSSFConditionalFormattingRule)sCF.CreateConditionalFormattingRule(ComparisonOperator.GreaterThanOrEqual, "19");
XSSFPatternFormatting fillGreen = (XSSFPatternFormatting)cfGreen.CreatePatternFormatting();
fillGreen.FillBackgroundColor = IndexedColors.LightGreen.Index;
fillGreen.FillPattern = FillPattern.SolidForeground;
//Fill Red if Passing Score
XSSFConditionalFormattingRule cfRed =
(XSSFConditionalFormattingRule)sCF.CreateConditionalFormattingRule(ComparisonOperator.LessThan, "19");
XSSFPatternFormatting fillRed = (XSSFPatternFormatting)cfRed.CreatePatternFormatting();
fillRed.FillBackgroundColor = IndexedColors.Red.Index;
fillRed.FillPattern = FillPattern.SolidForeground;
CellRangeAddress[] cfRange = { CellRangeAddress.ValueOf("A1:A6") };
sCF.AddConditionalFormatting(cfRange, cfGreen, cfRed);

iText C# exact text displaying

I am trying to insert the exact text with the spaces at the beginning of line, however iText eats all the spaces before the first visible symbol (tabulation does't work as well).
I am using iText 7 Community edition.
C# code:
FileInfo file = new FileInfo(DEST);
file.Directory.Create();
//Initialize PDF writer
PdfWriter writer = new PdfWriter(DEST);
//Initialize PDF document
PdfDocument pdf = new PdfDocument(writer);
// Initialize document
Document doc = new Document(pdf);
doc.Add(new Paragraph("Test\n\tTest\n Test\n Test 1 2 3"));
doc.Close();
That code display the text in the output .pdf document as
Test
Test
Test
Test 1 2 3
Without any tabs and spaces before the fist visible symbol of each line.
How can I change code to get
Test
Test
Test
Test 1 2 3
in the output document?
In your code example, (embedded) tabs wouldn't work in iTextSharp 5.xx.xx either, although spaces are respected. What's a little surprising, as you've proved, is that iText7 strips spaces following a newline. Not sure if you need support for either or both, so will give an example that handles each case separately:
First, preserving tabs:
Paragraph p = new Paragraph("Line 0\n")
.AddTabStops(new TabStop(8f))
// change to your needs ^^
.Add(new Tab())
.Add("Line 1");
doc.Add(p);
Second, preserving spaces immediately following a newline:
string[] lines = "0\n1\n 2\n 3\n".Split(
new string[] { "\n" },
StringSplitOptions.RemoveEmptyEntries
);
p = new Paragraph().AddStyle(
new Style().SetFont(PdfFontFactory.CreateFont(FontConstants.COURIER))
);
foreach (var l in lines)
{
if (Regex.IsMatch(l, #"^\s+"))
{
p.Add(" ") // all spaces stripped, whether one or more characters
.Add(l) // now leading whitespace preserved
.Add("\n");
}
else
{
p.Add(l).Add("\n");
}
}
doc.Add(p);
This is the first time I've looked at/written any iText7, so there's likely a different/better way, and I don't consider it anything but a workaround. Oddly, if you add any number of space characters following a newline and then immediately add a string that's also preceded with space characters, the first call strips space, but the second preserves them.
As a side note, one thing I noticed right away and really like about the new API is you can use method chaining all over the place. :)
Here's the result:
You should use Chunks to add text to a paragraph.
Then you should set tab settings and use specific Chunk.TABBING
p = new Paragraph();
p.setTabSettings(new TabSettings(56f));
p.add(Chunk.TABBING);
p.add(new Chunk("Hello World with tab."));
This sample is located at iText examples
Just try this.
Font bodyFont = FontFactory.GetFont("Times New Roman", 10, Font.NORMAL);
file.Directory.Create();
//Initialize PDF writer
PdfWriter writer = new PdfWriter(DEST);
//Initialize PDF document
PdfDocument pdf = new PdfDocument(writer);
// Initialize document
Document doc = new Document(pdf);
doc.Add(new Paragraph("Test", bodyFont));
doc.Add(new Paragraph(" Test", bodyFont));
doc.Add(new Paragraph(" Test", bodyFont));
doc.Add(new Paragraph(" Test 1 2 2", bodyFont));
doc.Close();

Bold Specific Elements from JSON Array in Rich Textbox

I'm currently facing an issue with the formatting of a chunk of text which is retrieved from a webserver as a JSON array.
What I am trying to acomplish is to format the text in a way that can be easily read by the user. An Example output of what I am trying to achieve is:
This is a Title
This is a little informative paragraph based on the subject selected
This is a secondary title
This is another paragraph
The way the string looks (before modification):
{"Title":"This is a Title", "Content_One": "This is alittle
informative paragraph based on the subject selected", "Title_Two":
"This is another paragraph"}
My current application is using Winforms, and I'm attempting to pump this into a Rich Text Box (hopefully going to handle the correct formatting). As a little long shot, I tried returning HTML Tags (Very long shot) For this to provide no change to the text.
I have also tried individually iterating through the array, and attempting to pramatically bold out certain elements from the JSON Array. None of which I have tried have provided expected output.
Attempt one:
TTKNormalContent.Text = new Font(ReturnArr.Title, FontStyle.Bold).ToString();
Which returns:
An unhandled exception of type
'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' occurred in
System.Core.dll
Attempt one:
TTKNormalContent.Text = ReturnArr.Title;
TTKNormalContent.SelectionFont = new Font(this.Font, FontStyle.Bold);
Which does not bold out the text
Attempt Two:
I can temporarily make the text bold by:
TTKNormalContent.Font = new Font(TTKNormalContent.Font, FontStyle.Bold);
TTKNormalContent.Text = ReturnArr.Title;
But adding:
TTKNormalContent.Font = new Font(TTKNormalContent.Font, FontStyle.Regular);
TTKNormalContent.Text += ReturnArr.ContentOne;
Which will remove the boldness
You need to use AppendText. When you use Text+= "something" you replace the format.
You can use this example:
var json = "{\"Title\":\"This is a Title\", \"Content_One\": \"This is alittle informative paragraph based on the subject selected\", \"Title_Two\": \"This is another paragraph\"}";
var start = 0;
Dictionary<string, string> values = new JavaScriptSerializer().Deserialize<Dictionary<string, string>>(json);
values.Cast<KeyValuePair<string, string>>()
.ToList()
.ForEach(item =>
{
this.richTextBox1.AppendText(item.Key);
this.richTextBox1.AppendText( ":" );
start += item.Key.Length + 1;
this.richTextBox1.AppendText(item.Value);
this.richTextBox1.Select(start, item.Value.Length);
this.richTextBox1.SelectionFont = new Font(this.richTextBox1.Font, FontStyle.Bold);
this.richTextBox1.AppendText("\n");
start += item.Value.Length + 1;
});
Screenshot:

Categories

Resources