bpampuch / pdfmake

Client/server side PDF printing in pure JavaScript
http://pdfmake.org
Other
11.64k stars 2.04k forks source link

table center alignment #72

Open dave-watts opened 10 years ago

dave-watts commented 10 years ago

IS it possible to align the table in the center of the page? All the

alignment: 'center',

code I add does nothing

bpampuch commented 10 years ago

wow, this made me think; I was about to answer: sure it is ;) but had troubles to provide an example

it looks like alignment is not taken into consideration in this case, I'll have to take a look at it

currently you can use the following workaround:

{
    columns: [
        { width: '*', text: '' },
        {
            width: 'auto',
                table: {
                        body: [
                                ['Column 1', 'Column 2', 'Column 3'],
                                ['One value goes here', 'Another one here', 'OK?']
                        ]
                }
        },
        { width: '*', text: '' },
    ]
},
dave-watts commented 10 years ago

nice, that does the job!

dave-watts commented 10 years ago

it would be nice to have a table sizing that sizes all other the cells according to the largest content

i.e. cellSize = max(cellSize)

or failing that, get text metrics to calculate cell size yourself

bpampuch commented 9 years ago

you mean equal widths for all columns based on largest width?

priyankaparihar commented 9 years ago

Hi, The above trick for getting the table center aligned dint work for me :( .

Could you please help me out fast.

Thanks.

bpampuch commented 9 years ago

what do you mean it didn't work? include your doc definition object, otherwise it's difficult to figure out what kind of problem you have

priyankaparihar commented 9 years ago

@bpampuch .. Thank you for the quick response. The table is not getting center aligned if my no. of columns are less. This trick which you have given dint work.

{ columns: [ { width: '', text: '' }, { width: 'auto', table: { body: [ ['Column 1', 'Column 2', 'Column 3'], ['One value goes here', 'Another one here', 'OK?'] ] } }, { width: '', text: '' }, ] },

The pdf is working perfectly for the table which has more number of columns.

This is how I am getting the table :

capture

bpampuch commented 9 years ago

the trick is to have first and last column start-sized; change width: '' to width: '*'

priyankaparihar commented 9 years ago

That is what I am doing exactly. The exact code is :

content : [ { width: '*', text: '' }, { width: 'auto', fontSize : 8, table : { headerRows : 1, body : otArr }

    },
    { width: '*', text: '' },
    ]
bpampuch commented 9 years ago

still can't reproduce this, could you include a complete example? thx

priyankaparihar commented 9 years ago

@bpampuch : Here is the actual code written for the same. I have removed the actual image data, due to the identity issue.

var pageOrientation; if (ori) pageOrientation = 'portrait'; else pageOrientation = 'landscape';

var docDefinition = {

    pageSize : 'A4',
    pageOrientation : pageOrientation,
    // [left, top, right, bottom] or [horizontal, vertical] or just a number
    // for equal margins
    pageMargins : [ 20, 50, 20, 45 ],
    footer : function(currentPage, pageCount) {
        return {
            margin : [ 20, 0, 20,20],
            fontSize : 8,
            columns : [
                    {
                        text : '' + datetime,
                        alignment : 'left',
                        bold : true
                    },
                    {
                        text : 'Page ' + currentPage.toString() + ' of '
                                + pageCount,
                        alignment : 'center',
                        bold : true
                    }, {
                        text : username,
                        alignment : 'right',
                        bold : true
                    } ]
        };
    },
    header : {
        margin : [20,10,20,0],
        columns : [
                {
                    image : 'data:image/png;==',
                    height : 30,
                    width : 70,
                    alignment : 'center'
                }, {
                    text : title.toUpperCase() + '\n' + date.toUpperCase(),
                    margin : [ -70, 0, 0, 0 ],
                    alignment : 'center',
                    fontSize : 10,
                    bold : true
                } ]
    },
    content : [ {
        widths : [ '*', 'auto', 100, '*' ],
        alignment : 'center',
        table : {
            headerRows : 1,
            alignment : 'center',
            body : otArr
        },
        fontSize : 8
    } ]
};
priyankaparihar commented 9 years ago

Hi @bpampuch .. Did you work on this issue. I have tried but could not get it worked.

blushi commented 7 years ago

https://github.com/bpampuch/pdfmake/pull/1087/

touchaqb commented 7 years ago

I have been struggling with this problem and I have found that, although it may be possible to workaround in some cases, there is a single point that makes a definite solution really hard to find.

@bpampuch workaround works for that specific case and @blushi pull request helps a lot. But both leave one problem unsolved.

The column approach causes pdfmake to crash when the table to be center aligned has any column width defined in %:

{
    content: [
        {
            columns: [
                { width: '*', text: '' },
                {
                    width: 'auto',
                    table: {
                            body: [
                                    ['Column 1', 'Column 2', 'Column 3'],
                                    ['One value goes here', 'Another one here', 'OK?']
                            ],
                            widths: ['auto', '80%', 'auto']
                    }
                },
                { width: '*', text: '' }
            ]
        }
    ]
}

@blushi pull request cannot properly centralize a table inside another table cell which is definied in %:

{
  "content": [
    {
      "table": {
        "body": [ [
          {

      "table": {
        "body": [
          ["1", "2", "3" ]
        ],
        "widths": [
          "auto", "auto", "auto"
        ]
      }, "tableAlignment": "center"

         }
        ]],"widths": ["80%"]}, "tableAlignment": "center"
    }
  ]
}

Both fail for the same reason: there is currently no treatment for column widths in % when it first attempts to calculate the column widths in points when tryLayoutDocument() does docStructure = this.docMeasure.measureDocument(docStructure);

Then it reaches measureTable(), which calls var measures = ColumnCalculator.measureMinMax(node.table.widths);

measureMinMax() happens to be:

//TODO: refactor and reuse in measureTable
function measureMinMax(columns) {
    var result = {min: 0, max: 0};

    var maxStar = {min: 0, max: 0};
    var starCount = 0;

    for (var i = 0, l = columns.length; i < l; i++) {
        var c = columns[i];

        if (isStarColumn(c)) {
            maxStar.min = Math.max(maxStar.min, c._minWidth);
            maxStar.max = Math.max(maxStar.max, c._maxWidth);
            starCount++;
        } else if (isAutoColumn(c)) {
            result.min += c._minWidth;
            result.max += c._maxWidth;
        } else {  // touchaqb: isn't a % column width test missing here?
            result.min += ((c.width !== undefined && c.width) || c._minWidth);
            result.max += ((c.width !== undefined && c.width) || c._maxWidth);
        }
    }

    if (starCount) {
        result.min += starCount * maxStar.min;
        result.max += starCount * maxStar.max;
    }

    return result;
}

The line I commented I belive that a test for % width column is missing.

In the column workaround, the last else is reached with c.width = "80%", variable result therefore becomes:

result.min = "41.320312580%41.3203125"
result.max = "107.67187580%51.029296875"

... which are not valid numbers.

It seems not to be an easy task to implement the missing else clause (test for % width) as the code at this point have no clue about the available width there is left for it to use so it could calculate the effective width in points. The availableWidth is only calculated later in the processing phase by buildColumnWidths() called either from layoutBuilder.js (for comuns) or tableProcessor.js (for tables).

As far as I understand the problem, it seems to me that some refactoring is needed in order to measureTable() be able to receive the available width and properly measure the table. Does anyone have another idea?

One thing I could no realize yet is how the star widths are being properly solved, perhaps % widths could work in a similar manner.

ontheterra commented 5 years ago

Just use '*' instead of int in widths option, and you are good to go

HeCorr commented 3 years ago

here we are... 7 years later and the issue is still present. 🙃

btw thank you very much, @bpampuch. your workaround worked (although if the content width is big enough it gets off-center to the right for some reason...)

Varkoff commented 1 year ago

Thank you for this workaround ;)