Avemey / zexmlss

ZEXMLSS Lazarus/Delphi component for read/write ods, excel xml, xlsx
http://avemey.com/zexmlss/index.php
Other
72 stars 52 forks source link

Delphi 2007 #33

Open MtwStark opened 4 years ago

MtwStark commented 4 years ago

Is it possible to set a cell to a unicode string value in delphi 2007 where string type is AnsiString?

MyWideString := 'сатри санҷиши юникод'; MyCell.AsString := MyWideString;

but in result xlsx MyCell will get '????? ??????? ??????'

the-Arioch commented 4 years ago

Option 1: Try explicit pre-conversion: MyCell.Data := UTF8Encode(MyWideString);
This should be the most universal but very boring and fragile solution. Perhaps the only one, if you really need different MVCS codepagesand can not set on the only one.

Option 2: If one non-unicode codepage is enough, then try explicitly specifying that non-UTF-8 codepage when saving XLSX. This way, the MyCell.Data := 'dsfsfsfsdfdsfdsfdsfds'; assignments are done as usual.

Below is the code from Delphi 2006 project.

The project uses Russian Windows codepage (1251). In your case there probably would be another codepage. Most probably one, returned by GetACP() Windows function.

uses zeSave;
// the project also should somewhere has `uses zeSaveXLSX` 
// the project also should somewhere has one of `uses zeZippyXXXX` - i'd use WinXP for early Delphi

     zxBook := TZEXMLSS.Create(....);

// generate report

      zxBook.SuppressedCellWarnings := [zvwNumbersAsText, zvw2DigitsYear];
      IntResult := TZXMLSSave.From(zxBook).Charset(1251).TO_(SaveToFile).Save;
      if(IntResult = 0) then
      begin
        OpenExcelApplication(SaveToFile);
      end {= if =};

Avemey, could you please put this snippet into some FAQ or at least mention in ReadMe ?

MtwStark commented 4 years ago

Hi, I have solved implementing WideString support depending on define DELPHI_UNICODE

in zsspxml.pas I have overloaded WriteRaw, all versions of WriteTag, CheckStrEntity and Correct_Entity with a WideString version

in ZEGetDefaultUTF8Converter I have bypassed @AnsiToUTF8 returning nil

P.S. in all versions of CheckStrEntity I had to add a filter for unsupported characters:

0..#31 (except #9, #10, #13), #127, #129, #141, #143, #144, #157

Also #160 replaced with a #32

in zexmlss.pas I have simply conditioned property Data (and all related variables and functions) to be WideString instead of string

Now it works like a charm in D2007

the-Arioch commented 4 years ago

I have simply conditioned property Data (and all related variables and functions) to be WideString Which means you now have your own fork that way, partially incompatible with mainstream and only custom-tailored for one specific project and compiler of yours.

Since FPC is more important than Delphi to Avemey i do not think he would go that way. Additionally, if these your changes were not isolated into a separate branch, they would start leaking into your master, which would probably mean Avemey would not be able to accept your pull requests on other features.

Also, using BSTR type means you multiplied memory use many times. We might expect that old Delphi is used on old computers, where RAM and CPU speed as not in such excess as on modern computers.

Perhaps a correct way would be declaring a type like TZString, and mapping it to different real types, dependent upon compiler used. TZString=UnicodeString on Delphi 2009+, =AnsiString on Delphi 2007-, =UTF8String on FPC

But even this would still mean RAM usage might get hugely multiplicated using WideString, so i wonder if that solution is universal.

Also #160 replaced with a #32

For example i would definitely prohibit this in MY project

MtwStark commented 4 years ago

In zsspxml.pas there is already the overloaded version conditioned by DELPHI_UNICODE define, I have only extended it.

If DELPHI_UNICODE is defined string type is already WideString so, in zexmlss.pas, in TZCell class, changing:

FData: string;

with:

{$IFDEF DELPHI_UNICODE} FData: string; {$ELSE} FData: WideString; {$ENDIF}

should not create a problem for newer Delphi.

Also, putting invalid characters in an excel cell will result in an error when opening the document, so I think that filtering them should be done.

160 is the   (non breaking space) but is invalid in excel cell, so in my opinion the choice is between filtering it or replacing with a normal space.