PHPWord: Creating an Arabic right to left word doc

2019-06-28 01:31发布

I'm trying to use PHPWord to create a word document that will include dynamic data pulled out from a MySQL database. The database has MySQL charset: UTF-8 Unicode (utf8) MySQL connection collation: utf8_unicode_ci and so does the table fields.

Data is stored and previewed fine in HTML, however when creating the document with the arabic variables, the output in Word looks like أحÙد Ùبار٠اÙÙرÙ.

$PHPWord = new PHPWord();
$document = $PHPWord->loadTemplate('templates/.../wtvr.docx');
$document->setValue('name', $name);
$document->setValue('overall_percent_100', $overall_percent_100);
$document->save('Individual Report - ' . $name . '.docx');

Is there anyway to fix that?

5条回答
甜甜的少女心
2楼-- · 2019-06-28 01:57

I had to fix it in two place different than Nasers's way:

1- in Section.php addText function:

I did this:

//$givenText = utf8_encode($text);
$givenText = $text;

2- in cell.php addText function

I did this:

// $text = utf8_encode($text);

now your word file will display unicode characters in right way. And then i had a problem in texts directions. i found the solution by using this code

$section->addText($val['notetitle'],array('textDirection'=>PHPWord_Style_Cell::TEXT_DIR_TBRL));

u can see the two constants in the cell.php file

const TEXT_DIR_TBRL = 'tbRl';
const TEXT_DIR_BTLR = 'btLr';

note that u can not apply other array combined styles like Paragraph before than 'textDirection' , because whose styles make 'textDirection' disabled.

查看更多
叛逆
3楼-- · 2019-06-28 02:03

Open PHPWord\Template.php
Change in setValue function (line no 89.) as below.
Change $replace = utf8_encode($replace); to $replace = $replace;

查看更多
The star\"
4楼-- · 2019-06-28 02:08

Find

$objWriter->startElement('w:t');
$objWriter->writeAttribute('xml:space', 'preserve'); // needed because of drawing spaces before and after text
$objWriter->writeRaw($strText);
$objWriter->endElement();

In Writer/Word2007/Base.php

replace with

$objWriter->startElement('w:textDirection');
$objWriter->writeAttribute('w:val', 'rlTb');
$objWriter->startElement('w:t');
$objWriter->writeAttribute('xml:space', 'preserve'); // needed because of drawing spaces before and after text
$objWriter->writeRaw($strText);
$objWriter->endElement();
$objWriter->endElement();

Also, make sure you don't use any styles to make it work, or else you will have to repeat this step in every function you use.

查看更多
Fickle 薄情
5楼-- · 2019-06-28 02:11
  • Please find the following points to write all types of utf-8 right to left data insertion in phpword template.

    1. In setValue function (line #95) in Template.php please comment the following portion of code

      //if(!is_array($replace)) {
      //    $replace = utf8_encode($replace);
      //}
      
    2. If you have problem with right to left which in some language the text mix up with left to right text add the following code in the same setValue function.

      $replace = "<w:rPr><w:rtl/></w:rPr>".$replace; 
      

//==== here is a working example of how the word data can be write inside the word template //--- load phpword libraries ----

    $this->load->library("phpword/PHPWord");
    $PHPWord  = new PHPWord();
    $document = $PHPWord->loadTemplate('./forms/data.docx');

    $document->setValue('NAME', 'شراف الدين');
    $document->setValue('SURNAME', 'مشرف');
    $document->setValue('FNAME', 'ظهرالدين');
    $document->setValue('MYVALUE', '15 / سنبله / 1363');
    $document->setValue('PROVINCE', 'سمنگان');
    $document->setValue('DNAME', 'عبدالله');
    $document->setValue('DMOBILE', '0775060701');   
    $document->setValue('BOX','<w:sym w:font="Wingdings" w:char="F06F"/>');
    $document->setValue('NO','<w:sym w:font="Wingdings" w:char="F06F"/>');
    //$document->setValue('BOX2','<w:sectPr w:rsidR="00000000"><w:pgSz w:w="12240" w:h="15840"/><w:pgMar w:top="1440" w:right="1440" w:bottom="1440" w:left="1440" w:header="720" w:footer="720" w:gutter="0"/><w:cols w:space="720"/><w:docGrid w:linePitch="360"/>');
    $document->setValue('YES','<w:sym w:font="Wingdings" w:char="F0FE"/>');

    $document->setValue('CLASS1','<w:sym w:font="Wingdings" w:char="F06F"/>');
    $document->setValue('CLASS2','<w:sym w:font="Wingdings" w:char="F0FE"/>');
    $document->setValue('DNAME','يما شاه رخي');
    $document->setValue('TEL','0799852369');
    $document->setValue('ENTITY','مشاور حقوقي و نهادي');
    $document->setValue('ENTITY','مشاور حقوقي و نهادي');
    $document->setValue('REMARKS','در مسابقات سال 2012 میلادی در میدان Judo   بر علاوه به تعداد  39 نفر در تاریخ 4/میزان/ سال 1391 قرار ذیل اند.');

    $file = "./forms/data2.docx";
    $document->save($file);
    header("Cache-Control: public");     
    header("Content-Description: File Transfer");     
    header("Content-Disposition: attachment; filename=data2.docx");     
    header("Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document");     
    header("Content-Transfer-Encoding: binary");         
    ob_clean();
    flush();
    readfile($file);

//need how design can change the looking. colr #E4EDF9enter image description here

查看更多
Animai°情兽
6楼-- · 2019-06-28 02:20

Well, yes. But you must unfortunately modify the library. The author of the library uses utf8_encode/utf8_decode obviously without understanding what they do at all.

On line 150, of Shared/String.php:

Replace

public static function IsUTF8($value = '') {
    return utf8_encode(utf8_decode($value)) === $value;
}

With

public static function IsUTF8($value = '') {
    return mb_check_encoding($value, "UTF-8");
}

Then, if you do

$ grep -rn "utf8_encode" .

On the project root, you will find all lines where utf8_encode is used. You will see lines like

$linkSrc = utf8_encode($linkSrc); //$linkSrc = $linkSrc;

$givenText = utf8_encode($text); //$givenText = $text;

You can simply remove the utf8_encode as shown in the comments.

Why is utf8_encode/utf8_decode wrong? First of all, because that's not what they do. They do from_iso88591_to_utf8 and from_utf8_to_iso88591. Secondly, ISO-8859-1 is almost never used, and usually when someone claims they use it, they are actually using Windows-1252. ISO-8859-1 is a very tiny character set, not even capable of encoding , let alone arabic letters.

You can do fast reviews of a library by doing:

$ grep -rn "utf8_\(en\|de\)code" .

If you get matches, you should move on and look for some other library. These functions simply do the wrong thing every time, and even if someone needed some edge case to use these functions, it's far better to be explicit about it when you really need ISO-8859-1, because you normally never do.

查看更多
登录 后发表回答