Rotate Text in Table Header

Hi,

Would like to know if there is any way to rotate a cell text header. I need to rotate 90º some of the text headers on the table. 

Thanks in advance fro your support.

Santi.

10 Replies

AP Anand Panchamoorthi Syncfusion Team December 7, 2020 01:49 PM UTC

Hi Santi, 

Thanks for contacting Syncfusion support. 
  
We can rotate text in header cells of PDF grid by using beginCellLayout call back. We can access an instance of PdfGrid and page/template graphics before drawing. And draw rotated text directly to the graphics based on the translate and rotate transformations on graphics. 
  
Please find the code snippet to rotate text of PDF grid header in 90/270 degree, 
//Create a new PDF document 
final PdfDocument document = PdfDocument(); 
//Add a new page 
final PdfPage page = document.pages.add(); 
//Gets page size 
final Size pageSize = page.getClientSize(); 
//Font used to draw text in PDF grid 
final PdfFont font = PdfStandardFont(PdfFontFamily.timesRoman, 25); 
 
//Create a new PDF grid 
final PdfGrid grid = PdfGrid(); 
//Set font of the text in PDF grid cells 
grid.style.font = font; 
//Add 3 columns 
grid.columns.add(count: 2); 
 
//Add headers in PDF grid 
grid.headers.add(1); 
//Header row with 90/270 degree rotated text 
final PdfGridRow header = grid.headers[0]; 
header.cells[0].value = '90 Degree Rotated'; 
header.cells[1].value = '270 Degree Rotated'; 
//Calculate height of 90/270 degree rotate text 
header.height = calculateHeightInRotation(header, font); 
 
//Add rows in PDF grid 
final PdfGridRow row1 = grid.rows.add(); 
row1.cells[0].value = 'Row 1 - Cell 1'; 
row1.cells[1].value = 'Row 1 - Cell 2'; 
final PdfGridRow row2 = grid.rows.add(); 
row2.cells[0].value = 'Row 2 - Cell 1'; 
row2.cells[1].value = 'Row 2 - Cell 2'; 
final PdfGridRow row3 = grid.rows.add(); 
row3.cells[0].value = 'Row 3 - Cell 1'; 
row3.cells[1].value = 'Row 3 - Cell 2'; 
 
//Call back function to rotate text in PDF grid cells 
grid.beginCellLayout = onBeginCellLayout; 
 
//Draw grid into PDF page 
grid.draw( 
    page: page, 
    bounds: Rect.fromLTWH(0, 0, pageSize.width, pageSize.height)); 
 
//Save PDF document 
final List<int> bytes = document.save(); 
 
//Call back function to rotate text in header cells 
void onBeginCellLayout(Object sender, PdfGridBeginCellLayoutArgs args) { 
  if (args.isHeaderRow) { 
    //Accessing grid instance 
    PdfGrid grid = sender as PdfGrid; 
    //Getting the value of corresponding cell 
    PdfGridCell cell = grid.headers[args.rowIndex].cells[args.cellIndex]; 
    dynamic value = cell.value; 
    if (value != null && value is String && value.isNotEmpty) { 
      //Save current graphics state 
      PdfGraphicsState state = args.graphics.save(); 
      if (args.cellIndex == 0) {//90 degree rotation 
        //Move current position to top-right of the cell bounds 
        args.graphics.translateTransform(args.bounds.right, args.bounds.top); 
        //Rotate graphics to 90 degree 
        args.graphics.rotateTransform(90); 
        //Draw string in rotated graphics at (0, 0) offset 
        //We can set X position of the offset as per the text alighments 
        args.graphics.drawString( 
            value, PdfStandardFont(PdfFontFamily.timesRoman, 25), 
            brush: PdfBrushes.black, 
            bounds: Rect.fromLTWH(0, 0, args.bounds.width, args.bounds.height)); 
      } else {//270 degree rotation 
        //Move current position to left-bottom of the cell bounds 
        args.graphics.translateTransform(args.bounds.left, args.bounds.bottom); 
        //Rotate graphics to 270 degree 
        args.graphics.rotateTransform(270); 
        //Draw string in rotated graphics at (0, 0) offset 
        //We can set X position of the offset as per the text alighments 
        args.graphics.drawString( 
            value, PdfStandardFont(PdfFontFamily.timesRoman, 25), 
            brush: PdfBrushes.black, 
            bounds: Rect.fromLTWH(0, 0, args.bounds.width, args.bounds.height)); 
      } 
      //Restore graphics 
      args.graphics.restore(state); 
      //Set empty seting for the value of grid cell 
      grid.headers[args.rowIndex].cells[args.cellIndex].value = ''; 
    } 
  } 
} 
 
//Calculate height of the grid row for 90 or 270 degree text rotation 
double calculateHeightInRotation(PdfGridRow row, PdfFont font) { 
  double height = 0; 
  for (int i = 0; i < row.cells.count; i++) { 
    dynamic value = row.cells[i].value; 
    if (value != null && value is String && value.isNotEmpty) { 
      Size size = font.measureString(value); 
      if (size.width > height) { 
        height = size.width; 
      } 
    } 
  } 
  return height; 
} 

  
Please let us know if you need further assistance in this. 

Anand Panchamoorthi 



SA Santi A December 7, 2020 04:36 PM UTC

Thanks a lot for your support Anand!

I have a small issue implementing my code. My table have 4 Headers Rows, and I have to rotate the texts on the headerRow4 so:

grid.headers.add(4);
// Add a grid header row
final PdfGridRow headerRow1 = grid.headers[0];
final PdfGridRow headerRow2 = grid.headers[1];
final PdfGridRow headerRow3 = grid.headers[2];
final PdfGridRow headerRow4 = grid.headers[3];

The height it's well applied by using the code below:
headerRow4.height = calculateHeightInRotation(headerRow4, font);

Then, the issue comes with the callback
grid.beginCellLayout = onBeginCellLayout;

I have modified the callback and specified the grid.headers[3].cells[args.cellIndex]

So, the callback is applying the rotation correctly for my cells values in headerRow4, but it is placing them inside the rowIndex[0] instead of rowIndex[3]. So, my question is how to restrict the onBeginCellLayout to my headerRow4.

Thanks again!

S.

void onBeginCellLayout(Object sender, PdfGridBeginCellLayoutArgs args) {
if (args.isHeaderRow) {
//Accessing grid instance
PdfGrid grid = sender as PdfGrid;
//Getting the value of corresponding cell
PdfGridCell cell = grid.headers[3].cells[args.cellIndex];
dynamic value = cell.value;
if (value != null && value is String && value.isNotEmpty) {
//Save current graphics state
PdfGraphicsState state = args.graphics.save();
if (args.cellIndex >= 0 && args.cellIndex <= 11) {
//90 degree rotation
//Move current position to top-right of the cell bounds
args.graphics
.translateTransform(args.bounds.left, args.bounds.bottom);
//Rotate graphics to 90 degree
args.graphics.rotateTransform(270);
//Draw string in rotated graphics at (0, 0) offset
//We can set X position of the offset as per the text alighments
args.graphics.drawString(
value, PdfStandardFont(PdfFontFamily.helvetica, 10),
brush: PdfBrushes.black,
bounds:
Rect.fromLTWH(0, 0, args.bounds.width, args.bounds.height));
}
//Restore graphics
args.graphics.restore(state);
//Set empty seting for the value of grid cell
grid.headers[args.rowIndex].cells[args.cellIndex].value = '';
}
}
}


AP Anand Panchamoorthi Syncfusion Team December 8, 2020 09:01 AM UTC

Hi Santi, 

Thanks for the information provided. 

We have validated your query and confirmed an issue with “Header row index is not retrieved properly in begin cell layout callback” as a defect. We will provide the fix on upcoming our weekly patch release planned 15th December, 2020. Please find the feedback link from https://www.syncfusion.com/feedback/20410/header-row-index-is-not-retrieved-properly-in-begin-cell-layout-callback

However we can calculate the current header index manually by using the below code snippet. 
int currentRowIndex = -1;  
 
//Call back function to rotate text in header cells  
void onBeginCellLayout(Object sender, PdfGridBeginCellLayoutArgs args) {  
  if (args.isHeaderRow) {  
    if (args.cellIndex) { 
      currentRowIndex++; 
    } 
  } 
  //We can use currentRowIndex instead of args.rowIndex for all header rows. 
  <<<Your code>>> 
} 

Please let us know if you need any further assistance in this. 

With Regards, 
Anand Panchamoorthi 



AP Anand Panchamoorthi Syncfusion Team December 15, 2020 11:26 AM UTC

Hi Santi,

Sorry for the inconvenience.

As we have planned public release in this Week, we doesn’t have weekly patch release for today. We will include this fix in our upcoming weekly patch release which is estimated to be available on 22nd Dec, 2020.

The status of the bug can be track through below link: https://www.syncfusion.com/feedback/20410/header-row-index-is-not-retrieved-properly-in-begin-cell-layout-callback

Please let us know if you have any other questions.

Regards,
Anand Panchamoorthi 



SA Santi A December 19, 2020 03:52 PM UTC

Thank you very much Anand, will wait till the 22nd then and in the meantime wish you a very nice Christmas.

Santi.


AP Anand Panchamoorthi Syncfusion Team December 22, 2020 06:46 AM UTC

Hi Santi, 

We have included the fix ‘Header row index is not retrieved properly in begin cell layout callback’ in our weekly patch release and the package v18.4.31-beta is rolled out. Please find the package from https://pub.dev/packages/syncfusion_flutter_pdf/versions/18.4.31-beta

We thank you for your support and appreciate your patience in waiting for this release. Please get in touch with us if you would require any further assistance. 

With Regards, 
Anand Panchamoorthi 



SA Santi A December 22, 2020 03:05 PM UTC

Thank you very much, rotation works fine now, the only issue I found is related to the background cell. If I paint before or after rotation the cells that I'm rotating, the text dissapears.

I have tried with following snippet code after my rotation code in onBeginCellLayout method.

grid.headers[args.rowIndex].cells[args.cellIndex].style
.backgroundBrush = PdfBrushes.orange;

And also before my rotation code with:

headerRow4.cells[5].style.backgroundBrush = PdfBrushes.orange;

Have a look on screeshots below showing roation with no cell background and with painted background:









AP Anand Panchamoorthi Syncfusion Team December 23, 2020 10:13 AM UTC

Hi Santi, 

Thanks for the detailed information provided.  

Assigning background brush is not a proper way, after drawing rotated text in graphics by using onBeginCellLayout method. In this case, We are forcing to draw rectangle with background brush on the text drawn. So, we suggest you to draw rectangle with the background brush before drawing rotated text in page/template graphics. The following code sample explains the same, 
//Call back function to rotate text in header cells 
void _onBeginCellLayout(Object sender, PdfGridBeginCellLayoutArgs args) { 
  if (args.isHeaderRow) { 
    //Accessing grid instance 
    final PdfGrid grid = sender as PdfGrid; 
    //Getting the value of corresponding cell 
    final PdfGridCell cell = grid.headers[args.rowIndex].cells[args.cellIndex]; 
    //Draw rectangle with background brush on the graphics before text rotation applied 
    if (cell.style.backgroundBrush != null) { 
      args.graphics.drawRectangle( 
          brush: cell.style.backgroundBrush, bounds: args.bounds); 
      cell.style.backgroundBrush = null; 
    } 
    final dynamic value = cell.value; 
    if (value != null && value is String && value.isNotEmpty) { 
      //Save current graphics state 
      final PdfGraphicsState state = args.graphics.save(); 
      if (args.rowIndex == 0) { 
        //90 degree rotation 
        //Move current position to top-right of the cell bounds 
        args.graphics.translateTransform(args.bounds.right, args.bounds.top); 
        //Rotate graphics to 90 degree 
        args.graphics.rotateTransform(90); 
        //Draw string in rotated graphics at (0, 0) offset 
        //We can set X position of the offset as per the text alighments 
        args.graphics.drawString( 
            value, PdfStandardFont(PdfFontFamily.timesRoman, 25), 
            brush: PdfBrushes.black, 
            bounds: Rect.fromLTWH(0, 0, args.bounds.width, args.bounds.height)); 
      } else { 
        //270 degree rotation 
        //Move current position to left-bottom of the cell bounds 
        args.graphics.translateTransform(args.bounds.left, args.bounds.bottom); 
        //Rotate graphics to 270 degree 
        args.graphics.rotateTransform(270); 
        //Draw string in rotated graphics at (0, 0) offset 
        //We can set X position of the offset as per the text alighments 
        args.graphics.drawString( 
            value, PdfStandardFont(PdfFontFamily.timesRoman, 25), 
            brush: PdfBrushes.black, 
            bounds: Rect.fromLTWH(0, 0, args.bounds.width, args.bounds.height)); 
      } 
      //Restore graphics 
      args.graphics.restore(state); 
      //Set empty seting for the value of grid cell 
      grid.headers[args.rowIndex].cells[args.cellIndex].value = ''; 
    } 
  } 
} 

//Calculate height of the grid row for 90 or 270 degree text rotation 
double _calculateHeightInRotation(PdfGridRow row, PdfFont font) { 
  double height = 0; 
  for (int i = 0; i < row.cells.count; i++) { 
    final dynamic value = row.cells[i].value; 
    if (value != null && value is String && value.isNotEmpty) { 
      final Size size = font.measureString(value); 
      if (size.width > height) { 
        height = size.width; 
      } 
    } 
  } 
  return height; 
} 

//Create a new PDF document 
final PdfDocument document = PdfDocument(); 
//Add a new page 
final PdfPage page = document.pages.add(); 
//Gets page size 
final Size pageSize = page.getClientSize(); 
//Font used to draw text in PDF grid 
final PdfFont font = PdfStandardFont(PdfFontFamily.timesRoman, 25); 
//Create a new PDF grid 
final PdfGrid grid = PdfGrid(); 
//Set font of the text in PDF grid cells 
grid.style.font = font; 
//Add 3 columns 
grid.columns.add(count: 2); 
//Add headers in PDF grid 
grid.headers.add(2); 
//Header row with 90/270 degree rotated text 
final PdfGridRow header1 = grid.headers[0]; 
header1.cells[0].value = '90 Degree Rotated'; 
//Assign background brush 
header1.cells[0].style.backgroundBrush = PdfBrushes.blue; 
header1.cells[1].value = '90 Degree Rotated'; 
//Assign background brush 
header1.cells[1].style.backgroundBrush = PdfBrushes.orange; 
//Calculate height of 90 degree rotate text 
header1.height = _calculateHeightInRotation(header1, font); 
final PdfGridRow header2 = grid.headers[1]; 
header2.cells[0].value = '270 Degree Rotated'; 
//Assign background brush 
Header2.cells[0].style.backgroundBrush = PdfBrushes.red; 
header2.cells[1].value = '270 Degree Rotated'; 
//Calculate height of 270 degree rotate text 
header2.height = _calculateHeightInRotation(header2, font); 
//Add rows in PDF grid 
final PdfGridRow row1 = grid.rows.add(); 
row1.cells[0].value = 'Row 1 - Cell 1'; 
row1.cells[1].value = 'Row 1 - Cell 2'; 
final PdfGridRow row2 = grid.rows.add(); 
row2.cells[0].value = 'Row 2 - Cell 1'; 
row2.cells[1].value = 'Row 2 - Cell 2'; 
final PdfGridRow row3 = grid.rows.add(); 
row3.cells[0].value = 'Row 3 - Cell 1'; 
row3.cells[1].value = 'Row 3 - Cell 2'; 
//Call back function to rotate text in PDF grid cells 
grid.beginCellLayout = _onBeginCellLayout; 
//Draw grid into PDF page 
grid.draw( 
    page: page, 
    bounds: Rect.fromLTWH(0, 0, pageSize.width, pageSize.height)); 
//Save PDF document 
final List<int> bytes = document.save(); 



Please let us know, if you need any further assistance in this. 
  
With Regards, 
Anand Panchamoorthi 



SA Santi A December 23, 2020 04:57 PM UTC

Thanks a lot Anan!

I got it and works fine. Thanks again for your support and wish you Merry Christmas and a Happy New Year !

Santi.


AP Anand Panchamoorthi Syncfusion Team December 24, 2020 07:29 AM UTC

Hi Santi, 
  
Thank you for the update. We glad to know that it works fine. 
  
With Regards, 
Anand Panchamoorthi 


Loader.
Up arrow icon