|
Posted by Jochem Maas on 09/20/05 16:24
Joseph Crawford wrote:
> I am not sure where you got the idea that it is creating an instance of word
I got the idea from your code, but I just gave it a quick glance...
that said you instantiate a new COM object in at least 3 places...
CreateHeader()
CreateDataSource()
CreateDocument()
which you mention might be the 'naughty' methods ... possibly then the culprit is
still the slow instantiation of multiple COM objects?
> for every record, but it creates one instance then loops through the records
> using that one instance.
>
> On 9/20/05, Jochem Maas <jochem@iamjochem.com> wrote:
>
>>Joseph Crawford wrote:
>>
>>>Hello Everyone,
>>>
>>>I have some code that is using COM to interact with MS Word to create a
>>
>>mail
>>
>>>merge based on my mysql database, however it is running dreadfully slow
>>>13.53846 seconds to be exact. This is only running on 34 records, i
>>
>>could
>>
>>>imagine running this on a few hundred records not to mention thousand.
>>
>>Is
>>
>>>COM usually this slow? These load times i believe to be accurate as they
>>>come from zend studio's profiler.
>>>You can see screenshots of the profile @
>>>http://codebowl.dontexist.net/bugs/MailMerge/ Below you will see my
>>
>>code,
>>
>>>anything you guys see that i could do to speed this up quite a bit i
>>
>>would
>>
>>>appreciate it. It seems the naughty methods are CreateHeader,
>>>CreateDataSource, CreateDocument.
>>>
>>>
>>>CODE
>>>=====================================================
>>><?php
>>>
>>>class MailMerge {
>>>private $mm_data_dir;
>>>private $obj;
>>>private $fieldcnt;
>>>private $rowcnt;
>>>private $letter_template;
>>>private $envelope_template;
>>>
>>>public function __construct($list = null, $letter = 'Has_Site',
>>
>>$envelope =
>>
>>>'Envelope', $data_dir = 'data/mailmerge') {
>>>if(!is_array($list)) throw new Exception('Cannot Create A Mail Merge
>>
>>With An
>>
>>>Empty List.');
>>
>>// an off topic thought...
>>if (!is_array($list) || empty($list)) { throw new Exception(' ... '); }
>>
>>more on topic ... you might try to make the com object
>>a singleton rather than creating a new one for each record
>>you are processing, and then clear the word document before
>>starting a new record... I could imagine starting up an
>>instance of Word for every record could be your bottleneck ...
>>given the ammount of time it takes to start up an interactive
>>instance of Word! (which is measured in seconds on my fairly
>>up2date laptop). i.e. only do this line once, for instance (untested):
>>
>>class MailMerge {
>>
>>static protected function getWord($clean = false)
>>{
>>static $obj;
>>if (!isset($obj)) {
>>$obj = new COM("word.application");
>>if ($obj instanceof COM) {
>>throw new Exception('I have no Word(s)');
>>}
>>}
>>
>>if ((boolean)$clean) {
>>/* todo: make the Word instance as new */
>>}
>>
>>return $obj;
>>}
>>
>>/* ... rest of class ... */
>>
>>private function CreateHeaderFile()
>>{
>>$this->obj = self::getWord();
>>
>>/* ... rest of method ... */
>>}
>>}
>>
>>
>>
>>
>>>$this->mm_data_dir = 'F:/htdocs/csaf/'.$data_dir;
>>>$this->list = $list;
>>>$this->letter_template = $letter;
>>>$this->envelope_template = $envelope;
>>>$this->initilize();
>>>
>>>$this->CreateHeaderFile();
>>>$this->CreateDataSource();
>>>$this->CreateDocument($this->letter_template);
>>>$this->CreateDocument($this->envelope_template);
>>>}
>>>
>>>public function __destruct() {
>>>unlink($this->mm_data_dir.'/ds.doc');
>>>unlink($this->mm_data_dir.'/header.doc');
>>>}
>>>
>>>private function initilize() {
>>>$this->rowcnt = count($this->list);
>>>$this->fieldcnt = count($this->list[0]);
>>>}
>>>
>>>private function Close() {
>>>$this->obj->Documents->Close();
>>>}
>>>
>>>private function Quit() {
>>>$this->obj->Quit();
>>>}
>>>
>>>private function Release() {
>>>$this->obj = NULL;
>>>}
>>>
>>>private function CreateHeaderFile() {
>>>$this->obj = new COM("word.application") or die('Couldnt load Word!');
>>>if(!is_object($this->obj)) throw new Exception('Unable to instanciate
>>>Word!');
>>>$this->obj->Documents->Add();
>>>
>>
>>$this->obj->ActiveDocument->Tables->Add($this->obj->Selection->Range,1,$this->fieldcnt);
>>
>>>for($i = 0; $i <= $this->rowcnt; $i++) {
>>>foreach($this->list[$i] as $key => $value) {
>>>$this->obj->Selection->TypeText($key);
>>>$this->obj->Selection->MoveRight();
>>>}
>>>}
>>>$this->obj->ActiveDocument->SaveAs($this->mm_data_dir.'/header.doc');
>>>$this->Close();
>>>$this->Quit();
>>>$this->Release();
>>>}
>>>
>>>private function CreateDataSource() {
>>>$this->obj = new COM("word.application");
>>>if(!is_object($this->obj)) throw new Exception('Unable to instanciate
>>>Word!');
>>>$this->obj->Documents->Add();
>>>
>>
>>$this->obj->ActiveDocument->Tables->Add($this->obj->Selection->Range,$this->rowcnt,$this->fieldcnt);
>>
>>>for($i = 0; $i <= $this->rowcnt; $i++) {
>>>foreach($this->list[$i] as $key => $value) {
>>>$this->obj->Selection->TypeText($value);
>>>$this->obj->Selection->MoveRight();
>>>}
>>>}
>>>$this->obj->ActiveDocument->SaveAs($this->mm_data_dir.'/ds.doc');
>>>$this->Close();
>>>$this->Quit();
>>>$this->Release();
>>>}
>>>
>>>private function CreateDocument($template) {
>>>$this->obj = new COM("word.application");
>>>if(!is_object($this->obj)) throw new Exception('Unable to instanciate
>>>Word!');
>>>$this->obj->Documents->Open($this->mm_data_dir.'/'.$template.'.dot');
>>>
>>
>>$this->obj->ActiveDocument->MailMerge->OpenHeaderSource($this->mm_data_dir.'/header.doc');
>>
>>$this->obj->ActiveDocument->MailMerge->OpenDataSource($this->mm_data_dir.'/ds.doc');
>>
>>>$this->obj->ActiveDocument->MailMerge->Execute();
>>>
>>
>>$this->obj->ActiveDocument->SaveAs($this->mm_data_dir.'/'.$template.'.doc');
>>
>>>$this->Close();
>>>$this->Quit();
>>>$this->Release();
>>>}
>>>}
>>>?>
>>>
>>
>
>
[Back to original message]
|