I am brand new to iText and leaped straight into iText 7, but find setting column widths on my table to be ridiculously challenging. Clearly there is something basic I'm not getting.
In combing the web for answers, I found some itext 5-based answers that don't seem to be relevant to itext 7 (hard-coding a fixed width). The iText 7 stuff seems to assume knowledge I don't have! "relative column widths" -- what does that mean? should the numbers add up to 100? Simple examples with 2 or 4 columns make sense, but I'm having difficulty translating that into a 7-column table.
I have a table with 7 columns. The 1st, 3rd, and 5th columns should be relatively narrow, they are simply labels. the 7th column can take up whatever space is available. For instance:
Col1 Col2 Col3 Col4 Col5 Col6 Col7
CMS#: C34827284 Date: 12/5/16 End Date: 12/6/16 approved
I thought I had it, but my latest attempt produces "Element does not fit current area" errors. Here is how I defined it
Table htable = new Table(new float[] {3, 8, 5, 10, 5, 10, 30});
These numbers add up to 71 so why do they not fit? Do they need to add exactly up to 100 or am I completely on the wrong track with the "adds up to 100" idea?
Did you define a width for the table as a whole?
This is what I tried:
public void createPdf(String dest) throws IOException {
//Initialize PDF writer
PdfWriter writer = new PdfWriter(dest);
//Initialize PDF document
PdfDocument pdf = new PdfDocument(writer);
// Initialize document
Document document = new Document(pdf, PageSize.A4);
// Create table
Table htable = new Table(new float[] {3, 8, 5, 10, 5, 10, 30});
htable.setFontSize(8);
htable.setWidthPercent(100);
htable.addHeaderCell(new Cell().add("Col1"));
htable.addHeaderCell(new Cell().add("Col2"));
htable.addHeaderCell(new Cell().add("Col3"));
htable.addHeaderCell(new Cell().add("Col4"));
htable.addHeaderCell(new Cell().add("Col5"));
htable.addHeaderCell(new Cell().add("Col6"));
htable.addHeaderCell(new Cell().add("Col7"));
htable.addCell(new Cell().add("CMS#"));
htable.addCell(new Cell().add("C34827284"));
htable.addCell(new Cell().add("Date:"));
htable.addCell(new Cell().add("12/5/16"));
htable.addCell(new Cell().add("EndDate:"));
htable.addCell(new Cell().add("12/6/16"));
htable.addCell(new Cell().add("Approved"));
// Add the table
document.add(htable);
// Close the document
document.close();
}
The result is shown here:
Note that I reduced the font size to avoid that more text is split the way CMS# is split.
Try adding htable.setWidthPercent(100); to your code if you didn't already do so. The problem should disappear.
Related
I have the following spreadsheet I am looking to solve a somewhat simple problem for:
Spreadsheet
Data tab contains the irregular data (as seen by the dates)
Chart 1 tab contains a working chart as I wish it to be presented
Chart 2 tab contains the new array structure I wish to populate
I cannot for the life of me figure out how to populate cell x,y on the Chart 2 array when matching x & y from the Data tab. ie - replicating 322 from cell Data - F3 to cell Chart 2 - H75 etc
INDEX - MATCH doesn't work as it references the cell location, not the cell contents - and as the array, I am graphing from is dynamic, this doesn't work.
The intended outcome is to be able to then QUERY the resultant data and plot an Age vs Weight chart instead of current Date vs Weight chart.
paste this into H4 cell and drag to the right:
=ARRAYFORMULA(IFERROR(VLOOKUP($G$4:$G, Data!$A$2:$U,
IFS(H2="Bear", 2,
H2="Bwuce", 3,
H2="Calcifer", 4,
H2="Capt. Kwazy Sox", 5,
H2="Chooie", 6,
H2="Lil Fibbs", 7,
H2="Howl", 8,
H2="JC", 9,
H2="Jim Rat", 10,
H2="Milo Jr", 11,
H2="Sgt. Simba Sox", 12,
H2="Angel", 14,
H2="Fern", 15,
H2="Fuzznut", 16,
H2="Houdini", 17,
H2="Kami", 18,
H2="Mumma Bear", 19,
H2="Rosie J", 20,
H2="Sophie", 21), 0), ))
I'm trying to add leading zeros to 'Record Number' special field provided by Crystal Reports 13.
Eg:
Record Number 1 should be '001'
Record Number 20 should be '020'
I have noticed that there's a related post about customizing table fields by using ToText({table.field},"000"). But this approach doesn't work when I use {recordnumber} instead of {table.field}.
Create a new formula to your desired field, then add this:
Right(("000" + ToText(({Comand.YourField}), 0, "")), 3)
That's it (note that if you need more zeros you can edit the formula. For 10 digits it will be Right(("0000000000" + ToText(({Comand.YourField}), 0, "")), 10) and so on.
As you completed your question, if you want RecordNumber use this way:
Right(("000" + ToText((RecordNumber), 0, "")), 3)
My question is probably really easy, but I am a mathematica beginner.
I have a dataset, lets say:
Column: Numbers from 1 to 10
Column Signs
Column Other signs.
{{1,2,3,4,5,6,7,8,9,10},{d,t,4,/,g,t,w,o,p,m},{g,h,j,k,l,s,d,e,w,q}}
Now I want to extract all rows for which column 1 provides an odd number. In other words I want to create a new dataset.
I tried to work with Select and OddQ as well as with the IF function, but I have absolutely no clue how to put this orders in the right way!
Taking a stab at what you might be asking..
(table = {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} ,
Characters["abcdefghij"],
Characters["ABCDEFGHIJ"]}) // MatrixForm
table[[All, 1 ;; -1 ;; 2]] // MatrixForm
or perhaps this:
Select[table, OddQ[#[[1]]] &]
{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}
The convention in Mathematica is the reverse of what you use in your description.
Rows are first level sublists.
Let's take your original data
mytable = {{1,2,3,4,5,6,7,8,9,10},{d,t,4,"/",g,t,w,o,p,m},{g,h,j,k,l,s,d,e,w,q}}
Just as you suggested, Select and OddQ can do what you want, but on your table, transposed. So we transpose first and back:
Transpose[Select[Transpose[mytable], OddQ[First[#]]& ]]
Another way:
Mathematica functional command MapThread can work on synchronous lists.
DeleteCases[MapThread[If[OddQ[#1], {##}] &, mytable], Null]
The inner function of MapThread gets all elements of what you call a 'row' as variables (#1, #2, etc.). So it test the first column and outputs all columns or a Null if the test fails. The enclosing DeleteCases suppresses the unmatching "rows".
Why are you not allowed to add days to a date in std.datetime? You can add months and years, but not days.
Recently I had to calculate a date for Easter Sunday, then I had to calculate related holidays (Ascension, Pentecost, Trinity, Corpus) by adding a certain number of days (39, 10, 7, 4) to the last date.
I ended up using dayOfYear:
date.dayOfYear(date.dayOfYear + offset);
This worked well, but only because I remained within the same year. What if I have to add 50 days to, say, dec 28?
Is there an easy way of doing this that I have overlooked?
You can use Duration from core.time.
Importing std.datetime will import core.time, so you can use it directly as follows.
import std.stdio, std.datetime;
void main() {
auto date = Date(2013, 12, 28);
writefln("%s + %s = %s", date, 10.days(), date + 10.days());
}
BTW, days() is an alias to dur!"days"() which constructs a Duration struct.
Check the documentation of core.time http://dlang.org/phobos/core_time.html for more information.
If you haven't read this article on std.datetime yet, then you probably should, as it will probably answer most basic questions that you have for how to use it.
But in general, core.time.Duration is what you should be using for adding and subtracting units from any of the time point types in std.datetime (SysTime, DateTime, Date, or TimeOfDay). So, you get code like
auto date = Date(2012, 12, 21);
date += dur!"days"(50);
or
auto date = Date(2012, 12, 21);
date += days(50);
(The templated dur function is the generic way to generate a Duration, but it has aliases for each of the units that it supports, so stuff like seconds(5) or 22.minutes() will work as well).
The add function exists for "months" and "years", because a Duration can't hold months or years (because you can't convert between them and smaller units without a specific date), and there needs to be a way to add months or years to a time point. Also, there's the question of what to do when you add or subtract a month or year to/from a date, and the month that it moves to doesn't include that day, so add accepts AllowDayOverflow in order to control that (which wouldn't be necessary with smaller units).
auto d3 = Date(2000, 2, 29);
d3.add!"years"(1);
assert(d3 == Date(2001, 3, 1));
auto d4 = Date(2000, 2, 29);
d4.add!"years"(1, AllowDayOverflow.no);
assert(d4 == Date(2001, 2, 28));
But add doesn't accept any other units, because you can simply use the normal arithmetic operations with a Duration. Also, subtracting two time points will result in a Duration.
assert(Date(2012, 12, 5) - Date(2002, 11, 17) == dur!"days"(3671));
assert(Date(2012, 12, 5) - dur!"days"(3671) == Date(2002, 11, 17));
Unlike add, roll accepts all of the units in the type rather than just "months" and "years", but that's because it's doing a different operation from +, and so adding or subtracting a Duration won't work (as that already adds or subtracts). Rather roll adds to a specific unit without adding to the others.
auto d = Date(2010, 1, 1);
d.roll!"days"(33);
assert(d == Date(2010, 1, 3));
You can useroll method:
date.roll!"days"(50);
I did overlook it: you can use dayOfGregorianCal:
import std.stdio, std.datetime;
void main() {
auto d = Date(2012, 12, 28);
writeln(d); // 2012-Dec-28
d.dayOfGregorianCal(d.dayOfGregorianCal + 50);
writeln(d); // 2013-Feb-16
}
I have a spatially enabled database (DB2, in this case). I need to store a large number of squares in a table. Which standard spatial SQL datatype is most suitable?
I guess I could use an ST_polygon, but maybe there is a more specialized type which would give
better performance
better data guarantees (I want to catch it as an error if someone where to store a non-square value in the particular column)
I've tried to find an ST_rectangle or ST_square type, but they don't seem to exist(?)
While I'm working with DB2, I'm also interested in solutions which don't work on DB2, as long as they are standards-compliant.
Even if your data represents a rectangle or square, you will still need to use the ST_POLYGON type. However, when you perform a query against the data, you can use a first-order filters such as ST_EnvIntersects.
Normally, a spatial database will compare the envelopes (i.e. a rectangle that contains the polygon) for an intersection. Then it performs the more expensive polygon-to-polygon intersection calculation. In this case, since your polygons are equal to the envelope, you can skip the second more expensive step.
As far as data validation, you can add a database trigger that checks ST_EQUALS(ST_ENVELOPE(geom),geom) = 1.
In DB2 it is also a Polygon. It looks like you are storing grids, so a quick check could be that if ST_ENVELOPE(geometry) == geometry then you have a square
This code is from
DB2's documentation
SET CURRENT PATH = CURRENT PATH, db2gse;
CREATE TABLE sample_geoms (id INTEGER, geometry ST_Geometry);
INSERT INTO sample_geoms VALUES
(1, ST_Geometry(ST_Point('point EMPTY',0)));
INSERT INTO sample_geoms VALUES
(2, ST_Geometry(ST_Point('point zm (10 10 16 30)' ,0)));
INSERT INTO sample_geoms VALUES
(3, ST_Geometry(ST_Multipoint('multipoint m (10 10 5, 50 10 6,
10 30 8)' ,0)));
INSERT INTO sample_geoms VALUES
(4, ST_Geometry(ST_Linestring('linestring (10 10, 20 10)',0)));
INSERT INTO sample_geoms VALUES
(5, ST_Geometry(ST_Polygon('polygon((40 120, 90 120, 90 150,
40 150, 40 120))',0)));
SELECT id, CAST(ST_AsText(ST_Envelope(geometry)) as VARCHAR(160)) Envelope
FROM sample_geoms;
Results:
ID ENVELOPE
----------- ---------------------------------------------------------------
1 -
2 POLYGON (( 9 9, 11 9, 11 11, 9 11, 9 9))
3 POLYGON (( 10 10, 50 10, 50 30, 10 30, 10 10))
4 POLYGON (( 10 9, 20 9, 20 11, 10 11, 10 9))
5 POLYGON (( 40 120, 90 120, 90 150, 40 150, 40 120))
See ID = 5? the last POLYGON == ST_ENVELOPE(geometry)
You may be looking for ST_Envelope -- I don't know for sure about DB2 but it is part of the OGC standard. Any non-vertical or non-horizontal line, or polygon, will generate a rectangle via this function, storing the coordinates typically as floats.