Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I resize an image in an HTML generated word document whilst retaining the aspect ratio?

I've been building a word document from some HTML as per these fantastic stackoverflow resources:

  • Office HTML Word header
  • How to use HTML to print header and footer on every printed page of a document?
  • HTML generated Microsoft Word document with header, footer and watermark

For those who are about to try it, prepare yourself for some pain as Word is patchy to say the least when it comes to what CSS it works with. If you want columns, you really need to go back to using tables to lay stuff out.

I've been having trouble with getting an image to size properly - There are images that the user uploads which will be used in this Word document, and I would like to resize them based on the 'height' property - to a height of 50px and then have the width scaled accordingly.

It seems there is no documentation for how to do this anywhere on the web.

I've also used some html2canvas code to turn a nice looking (CSS-based) bar-chart into an image, which is then usable directly in the word document as per the excellent http://www.kubilayerdogan.net/?p=304.

This image is not printing out well, so I'm planning to make the source HTML larger on screen (hidden in memory) (using jQuery) before running the html2canvas code on it - this way I'll have a larger image which I can then reduce in size and get a higher DPI number.

Firstly, I've learned that CSS width and height have no impact on images in Word. Similarly, the following doesn't work.

<img class="cobrandedlogo" src="' . $logourl . '" height="50px" />';

But I have found that using 'points' works like so:

<img class="cobrandedlogo" src="' . $logourl . '" height="50" />';

But this produces a very stretched image (depending on the source material of course). I want it to be scaled according to the original image.

I'm using PHP.

I've discovered this SO article which it seems will help: Calculating image size ratio for resizing

Here's some code I've been using:

jQuery code to generate the image of a div, modify the displayed HTML a bit and submit it to a PHP file:

var wordreport = jQuery('#container').clone();
jQuery(wordreport).find('#stats').html('<img src="http://improvedemployees.com/assets/teamstats/' + jQuery('#imgname').val() + '" />');
jQuery(wordreport).find('.columncontainer').each(function() {
    jQuery(this).children().wrapAll('<table><tr>');
});
// these were 3 columns on the screen - converted to a table and tds for Word
jQuery(wordreport).find('.memberstrengths').wrap('<td valign=top>'); 
jQuery(wordreport).find('.membercommunication').wrap('<td valign=top>');
jQuery(wordreport).find('.memberimproving').wrap('<td valign=top>');

jQuery(wordreport).find('#generateword').remove();
jQuery(wordreport).find('script').remove();             

var htmlpluscss = jQuery(wordreport).html();
htmlpluscss = '<style>.reportsection {border:1px solid #fff!important; padding:0px; margin-bottom:0px;}</style>' + htmlpluscss;
jQuery('#dochtml').val(htmlpluscss);
jQuery('#rawhtml').val(htmlpluscss);
jQuery('#stats').html2canvas({
    onrendered: function (canvas) {
        //Set hidden field's value to image data (base-64 string)
        jQuery('#img_val').val(canvas.toDataURL("image/png"));
        //Submit the form manually
        document.getElementById("getword").submit();
    }
});         

Also this HTML for the button to generate the word doc:

<div id="generateword">
<form method="post" action="/createword.php" target="_blank" id="getword"> 
<input type="hidden" name="docname" id="docname" />
<input type="hidden" name="dochtml" id="dochtml" />
<input type="hidden" name="orientation" id="orientation" value="landscape" />
<input type="hidden" name="logourl" value="<?php echo get_user_meta(get_current_user_id(), 'reportlogourl', true); ?>" />
<input type="hidden" name="img_val" id="img_val" value="" />
<input type="hidden" name="imgname" id="imgname" value="<?php echo $_GET['teamid']; ?>.png" />
<input type="button" value="View in Word" id="createword" />
</form>
</div>

Finally - here's the PHP file I used:

<?php

header("Content-type: application/vnd.ms-word");
header("Content-Disposition: attachment;Filename=" . $_POST['docname'] . ".doc");

$filteredData=substr($_POST['img_val'], strpos($_POST['img_val'], ",")+1);
//Decode the string
$unencodedData=base64_decode($filteredData);
//Save the image
$imgfile = $_POST['imgname'];
//file_put_contents("/assets/teamstats/" . $imgfile, $unencodedData);
file_put_contents("assets/teamstats/" . $imgfile, $unencodedData);

$orientation = 'portrait';
if(isset($_POST['orientation'])) {
$orientation = 'landscape';
}
$logourl = '';
if(isset($_POST['logourl'])) {
$logourl = $_POST['logourl'];
}

echo '<html xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:w="urn:schemas-microsoft-com:office:word"
xmlns:m="http://schemas.microsoft.com/office/2004/12/omml"
xmlns="http://www.w3.org/TR/REC-html40">
<head><meta http-equiv=Content-Type content="text/html; charset=utf-8"><title></title>
<style>
v\:* {behavior:url(#default#VML);}
o\:* {behavior:url(#default#VML);}
w\:* {behavior:url(#default#VML);}
.shape {behavior:url(#default#VML);}
</style>
<style>
@page
{
';
if ($orientation == 'landscape') {
    echo 'mso-page-orientation: landscape;
    size:29.7cm 21cm;    margin:1cm 1cm 1cm 1cm;';
}
else {
    echo 'mso-page-orientation: portrait;
    size:21cm 29.7cm;    margin:1cm 1cm 1cm 1cm;';
}
echo '
}
@page Section1 {
    mso-header-margin:.5in;
    mso-footer-margin:.5in;
    mso-header: h1;
    mso-footer: f1;
    }
div.Section1 { page:Section1; 
font-family:Helvetica; 
';
if ($orientation == 'landscape') {
    echo 'font-size:12px; ';
}
else {
    echo 'font-size:14px; line-height:20px;';
}
echo '
text-align:left;}
table#hrdftrtbl
{
    margin:0in 0in 0in 900in;
    width:1px;
    height:1px;
    overflow:hidden;
}
p.MsoHeader {
';
if ($orientation == 'landscape') {
    echo '    tab-stops:right 29.0cm;';
}
else {
    echo '    tab-stops:right 21.0cm;';
}
echo '
}
p.MsoFooter, li.MsoFooter, div.MsoFooter
{
    margin:0in;
    margin-bottom:.0001pt;
    mso-pagination:widow-orphan;
';
if ($orientation == 'landscape') {
    echo 'tab-stops:center 14.5cm right 29.0cm;';
}
else {
    echo 'tab-stops:center 10.5cm right 21.0cm;';
}
echo '
    font-size:12px;
}

</style>
<xml>
<w:WordDocument>
<w:View>Print</w:View>
<w:Zoom>100</w:Zoom>
<w:DoNotOptimizeForBrowser/>
</w:WordDocument>
</xml>
</head>';
echo "<body>";
echo '<div class="Section1">';
echo $_POST['dochtml'];
echo '<style>h3, table {
margin-top:0px!important;
}
div.membername {
margin-bottom:0px!important;
margin-top:0px!important;
height:39px!important;
line-height:25px!important;
}
div.membername, span.membershape, span.membertraits {
height:39px!important;
line-height:25px!important;
padding:0px!important;
margin:0px!important;
}
h2.membername {
margin-top:0px!important;
margin-bottom:0px!important;
padding-top:0px!important;
padding-bottom:0px!important;
line-height:25px;
height:25px!important;
font-size:24px!important;
}
table.tdmembername, table.tdmembername tr, table.tdmembername td, table.tdmembername span {
background-color:black!important;
}
div.columncontainer {
margin-top:0px!important;
}
img.cobrandedlogo {
max-height:50px;
height:50px;
}
</style>
';
echo '
<br/>
    <table id="hrdftrtbl" border="0" cellspacing="0" cellpadding="0">
    <tr><td>        <div style="mso-element:header" id=h1 >
            <p class=MsoHeader ><img src="http://improvedemployees.com/img/logo-x50.png" style="height:50px" height="50px"/><span style=mso-tab-count:1"></span>';
if ($logourl != "") {
    $newheight = 50;
    list($originalwidth, $originalheight) = getimagesize($logourl);
    $ratio = $originalheight / $newheight;
    $newwidth = $originalwidth / $ratio;
    echo '<img class="cobrandedlogo" src="' . $logourl . '" height="50" width="' . $newwidth . '" />';

}
echo '</p>
        </div>
    </td>
    <td>
    <div style="mso-element:footer" id=f1><span style="position:relative;z-index:-1"> 
        <p class=MsoFooter>
           <span style=mso-tab-count:1"></span>
            www.improvedemployees.com
           <span style=mso-tab-count:1"></span>
           Page <span style="mso-field-code: PAGE "><span style="mso-no-proof:yes"></span> of <span style="mso-field-code: NUMPAGES "></span></span>
        </p>
    </div>



    <div style="mso-element:header" id=fh1>
        <p class=MsoHeader><span lang=EN-US style="mso-ansi-language:EN-US">&nbsp;<o:p></o:p></span></p>
        </div>
        <div style="mso-element:footer" id=ff1>
        <p class=MsoFooter><span lang=EN-US style="mso-ansi-language:EN-US">&nbsp;<o:p></o:p></span></p>
    </div>

    </td></tr>
    </table>
</div>';
echo "</body>";
echo "</html>";

?>

How can I resize the images I'm inserting into word (using HTML) using just the height or width, so that Word retains the aspect ratio?

like image 829
Dave Hilditch Avatar asked Jul 16 '13 20:07

Dave Hilditch


1 Answers

I've managed to solve this myself:

If you want to scale an image based on one side in word using HTML then this code will do it:

$newheight = 50;
list($originalwidth, $originalheight) = getimagesize($logourl);
$ratio = $originalheight / $newheight;
$newwidth = $originalwidth / $ratio;
echo '<img class="cobrandedlogo" src="' . $logourl . '" height="50" width="' . $newwidth . '" />';

Swap newheight and newwidth if you want to scale based on the width instead.

like image 82
Dave Hilditch Avatar answered Sep 30 '22 20:09

Dave Hilditch