11

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

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?

Community
  • 1
  • 1
Dave Hilditch
  • 5,299
  • 4
  • 27
  • 35
  • If you're using PHP you can't use jQuery. And, scaling an image up, then scaling it down again won't improve things. This whole question is muddled. Please reword it and include some sample code so we can see what you're doing. –  Jul 16 '13 at 20:56
  • I'm using jQuery on the page where the report is presented to the user - there is an online version of the report available too. – Dave Hilditch Jul 16 '13 at 21:05
  • I use the .clone() method to clone the div in question that contains the report and then add and remove elements as required before posting them to the PHP file. This is also how I post the image binary to the PHP file so that the image can be saved server side then used in the word doc. You would understand if you'd tried to use Word HTML! – Dave Hilditch Jul 16 '13 at 21:08
  • re: Scaling an image up and then down again - are you sure? I'm pretty certain that if I load a 1000x500px image into Word and resize it down to 100x50px I get better DPI on the printout than if I just use a straight 100x50px image which I know gives jagged edges. – Dave Hilditch Jul 16 '13 at 21:11

1 Answers1

12

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.

Dave Hilditch
  • 5,299
  • 4
  • 27
  • 35