avemey / zexmlss Goto Github PK
View Code? Open in Web Editor NEWZEXMLSS Lazarus/Delphi component for read/write ods, excel xml, xlsx
Home Page: http://avemey.com/zexmlss/index.php
License: Other
ZEXMLSS Lazarus/Delphi component for read/write ods, excel xml, xlsx
Home Page: http://avemey.com/zexmlss/index.php
License: Other
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 '????? ??????? ??????'
"Default" style is only one specific variant of inheritance.
General case is provided using "ss:Parent" attribute
http://msdn.microsoft.com/en-us/library/office/aa140066(v=office.10).aspx#odc_xmlss_ss:style
При попытке скомпилировать пакет ошибки
zexml.inc(25,5) Error: Incompatible types: got "AnsiString" expected "Extended"
zexml.inc(25,5) Error: Compile time expression: Wanted Boolean but got <erroneous type> at IF or ELSEIF
zexml.inc(25,5) Error: Incompatible types: got "AnsiString" expected "Extended"
zexml.inc(25,5) Error: Compile time expression: Wanted Boolean but got <erroneous type> at IF or ELSEIF
исправление
// Archivers for Delphi, not used for Free Pascal / Lazarus
// Архиваторы для Delphi, не используются для Free Pascal / Lazarus
+++ {$IFNDEF FPC}
{ use Delphi XE2 and above }
{$if CompilerVersion >= 23.0} // bds xe2 (2012)
{$define XE2ZIP}
{$ifend}
и потом
{ use Synopse }
{//$define SYNZIP}
+++ {$EndIf}
// Free Pascal / Lazarus
{$IFDEF FPC}
...later, iterating through the worksheet this creates unxexpected data type conversion errors.
D:\DelphiProjects\Libs\zexmlss.Vanilla\zexmlss\src\zexlsx.pas
function ZEXSLXReadSheet(var XMLSS: TZEXMLSS; var Stream: TStream; const SheetName: string; var StrArray: TStringDynArray; StrCount: integer;
This is how row counter is being maxing out, by call to this helper routine.
//Проверить кол-во строк
procedure CheckRow(const RowCount: integer);
begin
if (_currSheet.RowCount < RowCount) then
_currSheet.RowCount := RowCount;
end;
This sets the correct cunt already:
procedure _GetDimension();
...
if (_maxR > 0) then
CheckRow(_maxR);
This later sets it again, thrice.
First go:
procedure _ReadSheetData();
...
if ((xml.TagName = 'row') and (xml.TagType in [TAG_TYPE_START, TAG_TYPE_CLOSED])) then
begin
_currCol := 0;
s := xml.Attributes.ItemsByName['r']; //индекс строки
if (s > '') then
if (TryStrToInt(s, t)) then
begin
_currRow := t - 1;
CheckRow(t);
end;
This is correct.
Second source:
procedure _ReadSheetData();
...
if (xml.TagType = TAG_TYPE_CLOSED) then
begin
inc(_currRow);
CheckRow(_currRow + 1);
end;
Looks reasonable - if we have a null, empty tag like <row/>
we need to uptick the counter.
Third source - copy-paste error!!!
procedure _ReadSheetData();
...
//конец строки
if ((xml.TagName = 'row') and (xml.TagType = TAG_TYPE_END)) then
begin
inc(_currRow); --- OOOOOPS !!!!
CheckRow(_currRow + 1);
end;
Hey, if you do parse </row>
- WHY would you increment the counter yet again???
You already did it above, don't do it again!
zexmlss/stuff/git_hooks/post-commit
Line 3 in 402ed40
git rev-parse HEAD
Берём ячейку со значением, внутри которого разные шрифты, надстрочные и подстрочные индексы, типа
<Cell ss:StyleID="s80">
<ss:Data ss:Type="String" xmlns="http://www.w3.org/TR/REC-html40">
<I>
<Font html:Color="#000000">L</Font>
<Sub>
<Font html:Color="#000000">0</Font>
</Sub>
<Font html:Color="#000000">– долгота осевого меридиана шестиградусной зоны [градусы];</Font>
</I>
</ss:Data>
</Cell>
Или
<Cell ss:StyleID="s70">
<ss:Data ss:Type="String" xmlns="http://www.w3.org/TR/REC-html40">
<I>
<Font html:Color="#000000">В – геодезическая широта рассматриваемого объекта</Font>
<Font html:Color="#FF0000">[радианы]</Font>
<Font html:Color="#000000">;</Font>
</I>
</ss:Data>
</Cell>
Открываем в компоненте, закрываем.... и не можем открыть в Экселе:
Ошибка XML в "Таблица"
Причина: Слишком много тегов
Файл: C:\xxxx.xml
Группа: Font
Тег: Font
Атрибут: Color
Значение: #000000
Вглядываемся - и находим там такие, ставшие вложенными структуры:
<Cell ss:StyleID="s27">
<ss:Data ss:Type="String" xmlns="http://www.w3.org/TR/REC-html40">
<Font html:Color="#FF0000">
<Font html:Color="#000000">В – геодезическая широта рассматриваемого объекта</Font>
[радианы]
</Font>
<Font html:Color="#000000">;</Font>
<I />
</ss:Data>
</Cell>
<Cell ss:StyleID="s37">
<ss:Data ss:Type="String" xmlns="http://www.w3.org/TR/REC-html40">
<Sub>
<Font html:Color="#000000">
<Font html:Color="#000000">L</Font>
0
</Font>
</Sub>
<Font html:Color="#000000">– долгота осевого меридиана шестиградусной зоны [градусы];</Font>
<I />
</ss:Data>
</Cell>
Добрый день, очень нравится Ваша работа!
Но хотелось бы примеры работы с TZEPicture и TZEChart
Спасибо!
Hello Ruslan,
I run into an out of memory problem when loading this Excel from the Romanian Chess federation:
http://frsah.ro/wp-content/uploads/2020/09/BAZA-JUCATORI-CU-DREPT-DE-JOC-CLUBURI-ACTIVE-01-SEPTEMBRIE-2020.xlsx
Here basically is my code:
var x:TZEXMLSS;
....
x := TZEXMLSS.Create(nil);
try
readXlsx(x, fromname);
except
DialogForm.runError('Error reading XLSX file');
end;
Is there a memory leak here?
Best regards, JP.
В модуле zsspxml есть функция CheckStrEntity(const st: ansistring; checkamp: boolean = true): ansistring;
. Крайний параметр указывает, что нужно все &
заменять на &
. Значение этого параметра выставлено по умолчанию и при вызове этой функции параметр нигде не меняется.
В итоге вот это:
formatCode="#,##0.00"р.""
меняется на это:
formatCode="#,##0.00&quot;р.&quot;"
При открытии такого файла Excel ругается.
Как мне кажется, нужно checkamp
наоборот установить в значение false
по дефолту, ибо всё равно при этом запустится процедура проверки Correct_Entity
, которая заменить &
только там, где нужно.
Здравствуйте.
Что-то не понимаю как в последней версии теперь открывать файл в delphi. Раньше была функция ReadXSLX, а теперь она
{$IFDEF FPC} function ReadXLSX(var XMLSS: TZEXMLSS; FileName: string): integer; {$ENDIF}
только для FPC.
Для сохранения тоже раньше использовал SaveXmlssToXLSX, теперь она для FPC.
zexmlss.pas(5907,19) Hint: Local variable "fcc" does not seem to be initialized
You confused TStream.Read and TStream.ReadBuffer!
procedure TZEPicture.AssignFromStream(AStream: TStream);
var
fcc: LongWord;
begin
if Assigned(FDataStream) then
FreeAndNil(FDataStream);
FFileName := '';
FDataStream := TMemoryStream.Create();
AStream.Position := 0;
// detect file type
--- AStream.Read(fcc, SizeOf(fcc));
+++ AStream.ReadBuffer(fcc, SizeOf(fcc));
if fcc = $474E5089 then
FFileName := '.png'
else if fcc = $E0FFD8FF then
FFileName := '.jpeg';
AStream.Position := 0;
FDataStream.CopyFrom(AStream, AStream.Size);
end;
можешь убрать из кода инклуды для zip'a ?
все равн оони ничег оне делают, только людей пугают...
{$IFDEF VER130}, sysd7 {$ENDIF}
zexmlss/zexmlss/src/zsspxml.pas
Line 29 in f67c73a
this unit seems to be nowhere found
this unit probably has to be included for D6/BCB6 also, not merely D5/BCB5?
I see in some issue reports that there are "patches", but are they merged into the GitHub repository?
And it seems the official website is not linking this GirHub? https://avemey.com/zexmlss/ ?
_WriteBorderItem in zexlsx.pas (line 4200)
_border := XMLSS.Styles[StyleNum].Border[BorderNum];
s1 := '';
++ if _border.Weight > 0 then
case _border.LineStyle of
ZEContinuous:
if _border.Weight > 0 then
case _border.LineStyle of
ZEContinuous:
begin
//thin ??
if (_border.Weight = 1) then
s1 := 'thin'; // 'hair'
else
if (_border.Weight = 2) then
s1 := 'medium'
else
s1 := 'thick';
end;
String (like Dynamic arrays) is pointer. Those lines are equivalent:
Hence condition "If Length(sss) <> 0" is not only hard to read - it is just much slower than straight "If sss <> '' "
Delphi XE2 dump:
zsspxml.pas.2799: if result > '' then
00701676 8B45FC mov eax,[ebp-$04]
00701679 833800 cmp dword ptr [eax],$00
0070167C 0F861CFFFFFF jbe $0070159e
zsspxml.pas.2811: if length(result) > 0 then
007016BF 8B45FC mov eax,[ebp-$04]
007016C2 8B00 mov eax,[eax]
007016C4 8945E8 mov [ebp-$18],eax
007016C7 8B45E8 mov eax,[ebp-$18]
007016CA 8945E4 mov [ebp-$1c],eax
007016CD 837DE400 cmp dword ptr [ebp-$1c],$00
007016D1 740B jz $007016de
007016D3 8B45E4 mov eax,[ebp-$1c]
007016D6 83E804 sub eax,$04
007016D9 8B00 mov eax,[eax]
007016DB 8945E4 mov [ebp-$1c],eax
007016DE 837DE400 cmp dword ptr [ebp-$1c],$00
007016E2 7E0C jle $007016f0
можно тебя попросить вывести скрипты в отдельную ветку, не связанную с улучшениями XLSX/ODF ?
ты уверен, что pretty-log нужно использовать %H а не %T ?
http://www.kernel.org/pub/software/scm/git/docs/git-log.html#_pretty_formats
Мне показалось, что %T правильнее, но м.б. я не так понимаю разницу
вообще это дико криво как-то, неужели линуксоиды считают это нормально, лишь каждая одна команда была простой и быстрой
Нет чтобы объединить filter drivers и макросы pretty log
Generated ODS file might be loaded erroneously by some spreadsheets, if the string cell type is not specified. Details were probably sent by e-mail in 2018. The fix is one-liner.
ss := 'string';
Hi,
I tried TZEXMLSS with delphi 10.0.
If I create a cell of type string or int everything is ok, but with float or datetime cells I have some problems.
I tried with
MyDoc.Sheets [0] .Cell [i, j] .Data: = FloatToStr (Mytab.Fields [i] .AsFloat); MyDoc.Sheets [0] .Cell [i, j] .CellType: = ZENumber;
and
MyDoc.Sheets [0] .Cell [i, j] .Data: = DateTimeToStr (Mytab.Fields [i] .Asdatetime); MyDoc.Sheets [0] .Cell [i, j] .CellType: = ZEDateTime;
and
TZXMLSSave.From(MyDoc).Charset('utf-8', TextConverter).Save(my_name);
but
in excel date cell is empty and float cell contain a date like 30/12/1899
can you help me?
Ты везде добавляешь '00' + HTMLColor
На самом деле надо добавлять 'ff'
И по хорошему при чтении надо проверять, что там в точности 8 символов, потому что по %%% стандарту - это до 4 байтов ограниченный w3c xmlBinary (ещё один %%% стандарт).
Кстати, может слегка плюнуть на старую Delphi и использовать TAlphaColor? И UITypes.TColorRec / UITypes.TAlphaColorRec чтобы с shr не трахаться?
[DCC Error] zesavecommon.pas(323): E2003 Undeclared identifier: 'FormatSettings'
Сделал я поиск по & QUOT ; и получается у тебя есть три несвязанных места
Хрень получается...
По хорошему нужен один список замен и РЯДОМ расположенные функции перевода в обе стороны.
А нарвался я на это, когда добавил сохранение NumberFormat в XML SS
И вот тут фокус просто прекрасный... когда сохраняем - делаем подмену на entity
А когда читаем - не делаем!
А при сохранение делаем подмену поверх подмены.
Хрень какая-то, похоже у тебя парсер несимметричный относительно подмен :-/
Using for XLSX export is problematic - there is a rather nasty bug in the ZipTV library, and the vendor is loooong gone west.
May 2019 was last time their site worked, and see what Delphi versions they ever knew...
However, i already made it in an attempt to add support for a legacy Delphi 5 project, so... Let it be merged into upstream.
This code would be useful for developers:
This code is dependent upon my quick fix for Delphi 5 compilation
From https://forum.lazarus.freepascal.org/index.php/topic,51546.0.html
FPC 3.2.0 and newer is stricter in checking that interface methods do indeed match correctly. The correct declaration of _AddRef and _Release is as they are declared in IInterface:
Code: Pascal [Select][+]
function _AddRef : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
function _Release : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
The problem is in XML parser lacking concept of XML namespaces, and then XML consumers forgetting to ignore namespaces either.
Fast fix below.
0001-OpenOffice.org-XML-2003-read.patch.txt
This is against my internal repo, which predates yours, so you can not apply it by means of Git, but pre-Git patch utilities should do.
Этот патч из моего репозитория, который был раньше твоего и у него дугой корень.
Git'ом ты его вряд ли применишь, нужно использовать вне-Git'овый (до-Git'овый) patch, либо руками.
Доброе время суток,
пользую ZColorStringGrid на дельфях, сейчас есть проект на Лазаре где хотелось бы его использовать. Может адаптируете? Желательно чтоб и под линукс с маком можно было скомпилить.
Спасибо
Hi,
I'm trying the numberformats-branch and in unit "zeodfs.pas" the procedure _ReadAutoFilter() contains two lines with calls to ReplaceStr(). I think it's better to use AnsiReplaceStr(), that way the code compiles in Delphi 7 too. Also, from what I can tell ReplaceStr() itself calls AnsiReplaceStr() with the same parameters. It probably won't result in a huge speed improvement though. 😉
http://msdn.microsoft.com/en-us/library/office/aa140066(v=office.10).aspx#odc_xmlss_ss:alignment
"Defines the font alignment attributes to use in this style. Each attribute that is specified is considered an override from the default."
Last "default" here does not mean "Default" style - there is Parent style notion, not Default style notion. It means pre-defined "default" value.
Тут смотри какая штука выходит
в случае ошибки желательно за собой все подчистить, не плодить мусор
но библиотеки делятся на два типа. Одни запускают сжатие при добавлении каждого стрима (в особо запущенном случае - асинхронно и одельным потоком, как ZipMaster, но вроде ZM и сериализует тоже, по крайней мере вроде на пятки сам себе ещё не наступал), другие эти стримы накапливают как "полётное задание", а реально отрабатывают по финальной отмашке.
2.1) Стримы после добавления не нужны, только память забивают
2.2) Стримы нужно хранить до фнального сжатия, и удалять только потом
2.1) При ошибке на диске уже лежит недобитый ZIP и его надо добить. Зато стримы уже должны быть освобождены по идее.
2.2) При ошибке на диске просто ничего не успевает создаться, и DoAbortAndDelete;
должна удалить файл, а для этого или надо удалить объект-зипппер, или скомандовать ему закрыть файл. Ну и опять же стримы поубивать, но это базовый класс должен сделать.
К какому типу относится Аббревия я не знаю, это тебе наблюдать.
А Глобалдьная закрывашка у тебя - да, пустой метод.
Пусть лучше будет 10 пустых методов, чем кто-то где-то забудет метод определить и будет тупить "почемуничегонеработает"
При создании новой ячейки TZCell через Create тип по умолчанию ставится ZEString, а при чтении файла с диска (созданного из Excel) тип по умолчанию (для всех ячеек, для которых тип не указан явно) ставится ZENumber. Это чем-то обусловлено?
Мне кажется правильнее будет при чтении тоже ставить ZEString или, как вариант, добавить настройку с дефолтным типом и при чтении ориентироваться на него.
Могу поправить сам, но хотелось бы знать Ваше мнение.
Excel 2010 just discards comments lacking authorId (but tolerates empty-string Author)
Excel then throws error like: Удаленный компонент: часть /xl/comments1.xml с ошибкой XML. (Примечания) Ошибка загрузки. Строка 2, столбец 139.
This is against my internal repo, which predates yours, so you can not apply it by means of Git, but pre-Git patch utilities should do.
0001-xlsx-export-fix-adding-cell-comments-from-internal-f.patch.txt
Этот патч из моего репозитория, который был раньше твоего и у него дугой корень.
Git'ом ты его вряд ли применишь, нужно использовать вне-Git'овый (до-Git'овый) patch, либо руками.
И так, если для объединенной ячейки поставить к примеру толстую рамку вокруг (без пересечения), то при считывании файла а потом его сохранения получаем такой баг.
Гриница остается слева и вверху, а низ и правая сторона остаются без границы.
Это все происходит из-за того, то для объединенной области всем ячейкам присваивается стиль верхней левой ячейки. Но так как у этой верхней левой ячейки стиль не содержит границ снизу и справа, получаем такой эффект.
вся проблема кроется вот в этом куске кода:
_in_merge_not_top := false;
k := _sheet.MergeCells.InMergeRange(j, i);
if (k >= 0) then
_in_merge_not_top := _sheet.MergeCells.InLeftTopCorner(j, i) < 0;
if (_in_merge_not_top) then
begin
k1 := _sheet.MergeCells.Items[k].Left;
k2 := _sheet.MergeCells.Items[k].top;
end
else
begin
k1 := j;
k2 := i;
end;
if (_sheet.Cell[k1, k2].CellStyle >= -1) and (_sheet.Cell[k1, k2].CellStyle < XMLSS.Styles.Count) then
s := IntToStr(_sheet.Cell[k1, k2].CellStyle + 1)
else
s := '0';
_xml.Attributes.Add('s', s, false);
если его заменить на этот, все заработает:
if (_sheet.Cell[j, i].CellStyle >= -1) and (_sheet.Cell[j, i].CellStyle < XMLSS.Styles.Count) then
s := IntToStr(_sheet.Cell[j, i].CellStyle + 1)
else
s := '0';
_xml.Attributes.Add('s', s, false);
Суть в том, что у ячеек должны оставаться свои же стили, ничего подменять не надо, так делает и сам офис.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.