I have a table with sensors data. There are sensors with long names that do not fit into a cell.
I want to add three points to end of the long sensor names (like text-overflow: ellipsis in css). I want to do it flexible without hardcoded values. Because in the future number of columns may be different.
How can I do it?
I create table like this:
var table = new PdfPTable(columns.Length);
var widths = new List<float>();
for (var i = 0; i < columns.Length; i++)
{
widths.Add(1f);
}
table.SetWidths(widths.ToArray());
And fill it:
for (var i = 0; i < columns.Length; i++)
{
var cell = new PdfPCell(new Phrase(columns[i], tableDataFont));
cell.UseAscender = true;
cell.HorizontalAlignment = Element.ALIGN_CENTER;
cell.VerticalAlignment = Element.ALIGN_MIDDLE;
cell.BackgroundColor = new Color(204, 204, 204);
cell.MinimumHeight = 20f;
table.AddCell(cell);
}
Something like this should work...
var text = "testtesttesttesttest";
var maxLength = 7;
var displayname = text;
if (text.Length > maxLength)
{
displayname = text.Substring(0, maxLength) + "...";
}
Considering you didn't post any code of your own, I can only provide some logic.
What I do here is just take the real value (insert that into text).
Declare a maximum length you want the text in your fields to be (maxLength).
Create a storage variable to for manipulation of the name without losing the original data (in case you want to keep that).
Then check if the text is longer than the maximumlength and replace all that is too long with "...".
You can then return "displayname" to whatever field you want it to be in.
This most likely isn't what you're looking for, but it does answer your question as it is right now.
Related
I know, that I can change color of all text in shape this way:
Shape.CellsU["Char.Color"].FormulaForceU = "RGB(255,255,255)";
There is also way to change color of certain characters in shape this way:
Characters.Begin = 2;
Characters.End = 5;
Characters.set_CharProps((short)MSVisio.VisCellIndices.visCharacterColor, (short)MSVisio.VisDefaultColors.visRed;);
But I can't find any way to pass custom RGB (or HEX or any type) value of color to just certain characters in shape. I don't want to cut shape into little shapes.
Can you please help? Thanks
The CharProps property allows you to set an index into the predefined document colors collection. For a custom RGB you can set the corresponding cell formula by first getting the row index with CharPropsRow like this:
var shp = vApp.ActiveWindow.Selection.PrimaryItem;
var shpChars = shp.Characters;
shpChars.Begin = 2;
shpChars.End = 5;
//shpChars.set_CharProps((short)Visio.VisCellIndices.visCharacterColor, (short)Visio.VisDefaultColors.visRed);
var targetRow = shpChars.CharPropsRow[0];
shp.CellsSRC[(short)Visio.VisSectionIndices.visSectionCharacter,
targetRow,
(short)Visio.VisCellIndices.visCharacterColor].FormulaU = "RGB(40,220,40)";
and that should give you similar results to this:
[Update] The above assumes you're targeting existing formating and changing it. To add new runs you can use CharProps first to add the row and then the CharPropsRow to target that new run. So you can run this code against a new page:
var vPag = vApp.ActivePage;
var shp = vPag.DrawRectangle(3,3,5,4);
shp.Text = "GoodMorning";
var shpChars = shp.Characters;
shpChars.Begin = 0;
shpChars.End = 4;
var targetRow = shpChars.CharPropsRow[(short)Visio.VisCharsBias.visBiasLetVisioChoose];
shp.CellsSRC[(short)Visio.VisSectionIndices.visSectionCharacter,
targetRow,
(short)Visio.VisCellIndices.visCharacterColor].FormulaU = "RGB(220,40,40)";
shpChars.Begin = 4;
shpChars.End = 11;
shpChars.set_CharProps((short)Visio.VisCellIndices.visCharacterColor, (short)Visio.VisDefaultColors.visBlack);
targetRow = shpChars.CharPropsRow[(short)Visio.VisCharsBias.visBiasLetVisioChoose];
shp.CellsSRC[(short)Visio.VisSectionIndices.visSectionCharacter,
targetRow,
(short)Visio.VisCellIndices.visCharacterColor].FormulaU = "RGB(40,200,40)";
...and this should result in the following:
I have to create a document with tables and nested tables. When the nested table is added to a column with a fixed width (in my example this is the first column with a width of 150pt) the nested table looks as expected (first column auto, second 70pt). But If I add the same nested table to a column where the width should automatically be adapted the columns of the nested table seems to be changed to auto as well. Is there something I have missed?
nested table example
The code to generate this example looks as follow
public void Test(){
//using (var stream = new MemoryStream())
var file = string.Format(#"c:\sample{0}.pdf", Guid.NewGuid());
var rand = new Random();
using (var pdfDoc = new PdfDocument(new PdfWriter(file)))
using (var doc = new Document(pdfDoc))
{
var table = new Table(new[] { UnitValue.CreatePointValue(150), UnitValue.CreatePointValue(0), UnitValue.CreatePointValue(0), UnitValue.CreatePercentValue(25)});
//table.SetWidthPercent(100);
for (var i = 0; i < table.GetNumberOfColumns(); i ++ )
{
var column = table.GetColumnWidth(i);
table.AddHeaderCell(new Cell().SetBackgroundColor(Color.LIGHT_GRAY).SetMargin(0).Add(column.ToString()));
}
const string sampledata = "01234567";
for (var i = 0; i < table.GetNumberOfColumns() * 6; i++)
{
switch (i)
{
case 6:
table.AddCell(new Image(ImageDataFactory.Create(#"c:\demo.jpg")));
break;
case 4:
{
var subTable = CreateSubTable("subtable", rand);
table.AddCell(new Cell().SetMargin(0).SetPadding(0).Add(subTable));
break;
}
case 9:
{
var subTable = CreateSubTable("subtable", rand);
table.AddCell(new Cell().SetMargin(0).SetPadding(0).Add(subTable));
break;
}
default:
table.AddCell(sampledata.Substring(0, rand.Next(1, sampledata.Length)));
break;
}
}
doc.Add(table);
}
private static Table CreateSubTable(string sampledata, Random rand){
var subTable = new Table(new[] {UnitValue.CreatePointValue(0), UnitValue.CreatePointValue(70)});
for (var h = 0; h < subTable.GetNumberOfColumns(); h++)
{
var column = subTable.GetColumnWidth(h);
subTable.AddHeaderCell(new Cell().SetBackgroundColor(Color.LIGHT_GRAY).SetMargin(0).Add(column.ToString()));
}
for (var j = 0; j < subTable.GetNumberOfColumns() * 4; j++)
{
subTable.AddCell(sampledata.Substring(0, rand.Next(1, sampledata.Length)));
}
return subTable;
}
Yes, you've missed something.
First of all, you can check the latest itext7 snapshot version and find your code working as you expect. See the result pdf
The difference is that in 7.0.2 auto layout itext do not consider column width in max width calculations. That has been changed and that's why now your code will work as you expect.
However, in certain conditions the same nested table will be processed differently. It depends on available width (in your case for second column - column with width to be calculated automatically). So generally speaking with certain cell content that will be impossible to place nested table as it should be (0 pt, 70 pt), and itext will squeeze the second column.
The good news is that we received too many questions about auto layout algorithm and decided to write some detailed documentation. I believe that will be finished in a week. And then everybody will be happy =)
In my progam I extracted text from a PDF file and it works well. ItextSharp extracts text from PDF line by line. However, when a PDF file contains 2 columns, the extracted text is not ok as in each line joins two columns.
My problem is: How can I extract text column by column?
Below is my code. PDF files are Arabic. I'm sorry my English is not so good.
PdfReader reader = new PdfReader(#"D:\test pdf\Blood Journal.pdf");
int intPageNum = reader.NumberOfPages;
string[] words;
string line;
for (int i = 1; i <= intPageNum; i++)
{
text = PdfTextExtractor.GetTextFromPage(reader, i,
new LocationTextExtractionStrategy());
words = text.Split('\n');
for (int j = 0, len = words.Length; j < len; j++)
{
line = Encoding.UTF8.GetString(Encoding.UTF8.GetBytes(words[j]));
// other things here
}
// other things here
}
You may want to use RegionTextRenderFilter to restrict a column region then use LocationTextExtractionStrategy to extract the text. However this requires prior knowledge to the PDF file your are parsing, i.e. you need information about the column's position and size.
In more details, you need to pass in the coordinates of your column to define a rectangle, then extract the text from that rectangle. A sample will be like this:
PdfReader reader = new PdfReader(#"D:\test pdf\Blood Journal.pdf");
int intPageNum = reader.NumberOfPages;
private string GetColumnText(float llx, float lly, float urx, float ury)
{
// reminder, parameters are in points, and 1 in = 2.54 cm = 72 points
var rect = new iTextSharp.text.Rectangle(llx, lly, urx, ury);
var renderFilter = new RenderFilter[1];
renderFilter[0] = new RegionTextRenderFilter(rect);
var textExtractionStrategy =
new FilteredTextRenderListener(new LocationTextExtractionStrategy(),
renderFilter);
var text = PdfTextExtractor.GetTextFromPage(reader, intPageNum,
textExtractionStrategy);
return text;
}
Here is another post discussing what you want, you may want to check as well: iTextSharp - Reading PDF with 2 columns. But they didn't hit the solution either :(
I'm entering data from a CSV file into a OpenOffice spreadsheet.
This code gets the a new sheet in a spreadsheet:
Public Spreadsheet getSpreadsheet(int sheetIndex, XComponent xComp)
{
XSpreadsheet xSheets = ((XSpreadsheetDocument)xComp).getSheets();
XIndexAccess xSheetIA = (XIndexAccess)xSheets;
XSpreadsheet XSheet = (XSpreadsheet)xSheetsA.getByIndex(sheetIndex).Value;
return XSheet;
}
I then have method that enters a list into a cell range one cell at a time. I want to be able to automatically set the column size for these cells. which is something like
string final DataCell;
Xspreadsheet newSheet = getSpreadsheet(sheetIndex, xComp);
int numberOfRecords = ( int numberOfColumns * int numberOfRows);
for(cellNumber = 0; cellNumber < numberOfrecords; cellNumber++)
{
XCell tableData = newSheet.getCellbyPosition(columnValue, rowValue);
((XText)tableData).setString(finalDataCell);
column Value++;
if(columnValue > = numberOfColumns)
{
rowVal++ column = 0;
}
}
After googling i have found the function:
columns.OptimalWidth = True on http://forum.openoffice.org/en/forum/viewtopic.php?f=20&t=31292
but im unsure on how to use this. Could anyone explain this further or think of another way to have the cell autofit?
I understand the comments in the code are in Spanish I think, but the code is in English. I ran the comments through Google translate so now they are in English. I copied it from here:
//Auto Enlarge col width
private void largeurAuto(string NomCol)
{
XCellRange Range = null;
Range = Sheet.getCellRangeByName(NomCol + "1"); //Recover the range, a cell is
XColumnRowRange RCol = (XColumnRowRange)Range; //Creates a collar ranks
XTableColumns LCol = RCol.getColumns(); // Retrieves the list of passes
uno.Any Col = LCol.getByIndex(0); //Extract the first Col
XPropertySet xPropSet = (XPropertySet)Col.Value;
xPropSet.setPropertyValue("OptimalWidth", new one.Any((bool)true));
}
What this does it this: First it gets the range name and then gets the first column. The real code, though, is XpropertySet being used, which is explained REALLY well here.
public void optimalWidth(XSpreadsheet newSheet)
{
// gets the used range of the sheet
XSheetCellCursor XCursor = newSheet.createCursor();
XUsedAreaCursor xUsedCursor = (XUsedAreaCursor)XCursor;
xUsedCursor.gotoStartOfUsedArea(true);
xUsedCursor.gotoEndOfUsedArea(true);
XCellRangeAddressable nomCol = (XCellRangeAddressable)xUsedCursor;
XColumnRowRange RCol = (XColumnRowRange)nomCol;
XTableColumns LCol = RCol.getColumns();
// loops round all of the columns
for (int i = 0; i < nomCol.getRangeAddress().EndColumn;i++)
{
XPropertySet xPropSet = (XPropertySet)LCol.getByIndex(i).Value;
xPropSet.setPropertyValue("OptimalWidth", new uno.Any(true));
}
}
I don't know the width of the texts in the textblock beforehand, and I want the the textblock to be aligned to the right like this, while still having the individual lines left-aligned:
Mr. Petersen |
Elmstreet 9 |
888 Fantastic City|
(| donotes the right edge of the document)
It should be simple, but I can't figure it out.
I've tried to put all the text in a paragraph and set paragraph.Alignment = Element.ALIGN_RIGHT, but this will rightalign the individual lines.
I've tried to put the paragraph in a cell inside a table, and rightalign the cell, but the cell just takes the full width of the table.
If I could just create a container that would take only the needed width, I could simply rightalign this container, so maybe that is really my question.
Just set the Paragraph.Align property:
using (Document document = new Document()) {
PdfWriter.GetInstance(
document, STREAM
);
document.Open();
for (int i = 1; i < 11; ++i) {
Paragraph p = new Paragraph(string.Format(
"Paragraph {0}", i
));
p.Alignment = Element.ALIGN_RIGHT;
document.Add(p);
}
}
It even works with a long string like this:
string longString = #"
iText ® is a library that allows you to create and manipulate PDF documents. It enables developers looking to enhance web- and other applications with dynamic PDF document generation and/or manipulation.
";
Paragraph pLong = new Paragraph(longString);
pLong.Alignment = Element.ALIGN_RIGHT;
document.Add(pLong);
EDIT:
After looking at the "picture" you drew...
It doesn't match with the title. The only way you can align individual Paragraph objects like your picture is if the "paragraph" does NOT exceed the Document object's "content" box (for a lack of a better term). In other words, you won't be able to get that type of alignment if the amount of text exceeds that which will fit on a single line.
With that said, if you want that type of alignment you need to:
Calculate the widest value from the collection of strings you intend to use.
Use that value to set a common left indentation value for the Paragraphs.
Something like this:
using (Document document = new Document()) {
PdfWriter.GetInstance(
document, STREAM
);
document.Open();
List<Chunk> chunks = new List<Chunk>();
float widest = 0f;
for (int i = 1; i < 5; ++i) {
Chunk c = new Chunk(string.Format(
"Paragraph {0}", Math.Pow(i, 24)
));
float w = c.GetWidthPoint();
if (w > widest) widest = w;
chunks.Add(c);
}
float indentation = document.PageSize.Width
- document.RightMargin
- document.LeftMargin
- widest
;
foreach (Chunk c in chunks) {
Paragraph p = new Paragraph(c);
p.IndentationLeft = indentation;
document.Add(p);
}
}
UPDATE 2:
After reading your updated question, here's another option that lets you add text to the left side of the "container":
string textBlock = #"
Mr. Petersen
Elmstreet 9
888 Fantastic City
".Trim();
// get the longest line to calcuate the container width
var widest = textBlock.Split(
new string[] {Environment.NewLine}
, StringSplitOptions.None
)
.Aggregate(
"", (x, y) => x.Length > y.Length ? x : y
)
;
// throw-away Chunk; used to set the width of the PdfPCell containing
// the aligned text block
float w = new Chunk(widest).GetWidthPoint();
PdfPTable t = new PdfPTable(2);
float pageWidth = document.PageSize.Width
- document.LeftMargin
- document.RightMargin
;
t.SetTotalWidth(new float[]{ pageWidth - w, w });
t.LockedWidth = true;
t.DefaultCell.Padding = 0;
// you can add text in the left PdfPCell if needed
t.AddCell("");
t.AddCell(textBlock);
document.Add(t);