1 / 1 / 1
Регистрация: 15.05.2014
Сообщений: 30
1

Иероглифы при экспорте данных из таблицы StringGrid в файл

17.09.2015, 23:02. Показов 2522. Ответов 6
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Пишу программу, выполняющую расчёты по заданным в программе формулам,

используя данные, которые загружаются из XML-файлов. На компьютерах, где

возможно будет использоваться программа может отсутствовать какой-либо

офисный пакет (ни MS Office, ни OpenOffice или LibreOffice), поэтому мною

была добавлена возможность создания Excel-файлы на основе данных из

StringGrid.

Использовал следующий код (взял из DelphiWorld, переделал для корректной

работы в Lazarus - добавил учёт типа данных - строковый тип, целое или

дробное число)

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
const
CXlsBof: array[0..5] of Word = ($809, 8, 00, $10, 0, 0);
CXlsEof: array[0..1] of Word = ($0A, 00);
CXlsLabel: array[0..5] of Word = ($204, 0, 0, 0, 0, 0);
CXlsNumber: array[0..4] of Word = ($203, 14, 0, 0, 0);
CXlsRk: array[0..4] of Word = ($27E, 10, 0, 0, 0);
 
procedure XlsWriteCellRk(XlsStream: TStream; const ACol, ARow: Word;
const AValue: Integer);
var
V: Integer;
begin
CXlsRk[2] := ARow;
CXlsRk[3] := ACol;
XlsStream.WriteBuffer(CXlsRk, SizeOf(CXlsRk));
V := (AValue shl 2) or 2;
XlsStream.WriteBuffer(V, 4);
end;
 
procedure XlsWriteCellNumber(XlsStream: TStream; const ACol, ARow: Word;
const AValue: Double);
begin
CXlsNumber[2] := ARow;
CXlsNumber[3] := ACol;
XlsStream.WriteBuffer(CXlsNumber, SizeOf(CXlsNumber));
XlsStream.WriteBuffer(AValue, 8);
end;
 
procedure XlsWriteCellLabel(XlsStream: TStream; const ACol, ARow: Word;
const AValue: string);
var
L: Word;
begin
L := Length(AValue);
CXlsLabel[1] := 8 + L;
CXlsLabel[2] := ARow;
CXlsLabel[3] := ACol;
CXlsLabel[5] := L;
XlsStream.WriteBuffer(CXlsLabel, SizeOf(CXlsLabel));
XlsStream.WriteBuffer(Pointer(AValue)^, L);
end;
 
function SaveAsExcelFile(AGrid: TStringGrid; AFileName: string): boolean;
const
{$J+}CXlsBof: array[0..5] of Word = ($809, 8, 00, $10, 0, 0);{$J-}
CXlsEof: array[0..1] of Word = ($0A, 00);
var
FStream: TFileStream;
I, J: integer;
float: extended; num:integer;
begin
Result := False;
FStream := TFileStream.Create(PChar(AFileName), fmCreate or fmOpenWrite);
try
CXlsBof[4] := 0;
FStream.WriteBuffer(CXlsBof, SizeOf(CXlsBof));
for i := 0 to AGrid.ColCount - 1 do
for j := 0 to AGrid.RowCount - 1 do
BEGIN
//проверяем, является ли ячейка целым числом
if TryStrToInt(AGrid.Cells[i,j], num) then
begin
XLSWriteCellNumber(FStream, I, J, (StrToInt(AGrid.cells[i, j])));
end
//проверяем, является ли ячейка дробным числом
else if TryStrToFloat(AGrid.Cells[i,j], float) then
begin
XLSWriteCellNumber(FStream, I, J, (StrToFloat(AGrid.cells[i, j])));
end
else BEGIN XLSWriteCellLabel(FStream, I, J, 
 
WideString(UTF8Decode(AGrid.cells[i, j]))); END;
END;
FStream.WriteBuffer(CXlsEof, SizeOf(CXlsEof));
Result := True;
finally
FStream.Free;
end;
end;
Создаваемый данным кодом файл отлично открывается в Microsoft Excel любых

версий (от Excel 97 до Excel 2013), но при открытии данного файла в

OpenOffice Calc или LibreOffice Calc русский текст отображается в виде

иероглифов, причём возможность задать нужную кодировку в настройках

программы отсутствует.

Первым делом я подумал, что может быть всё дело в том, что при создании

файла используется перекодировка из UTF8 в системную (то есть

WINDOWS-1251).
Delphi
1
WideString(UTF8Decode(AGrid.cells[i, j])))
Но буквально только что я набросал небольшую программку в Delphi 5,

скопировал в неё код из



Delphi World
и запустил. При открытии созданного файла в LibreOffice

по прежнему отображаются иероглифы.

При этом неделю назад, когда мне понадобилось загрузиться с LiveCD,

запустил имеющийся в нём Softmaker Office (очередной бесплатный клон MS

Office) и открыл в программе PlanMaker получившуюся таблицу, она открылась

вполне корректно, точно также, как и в Microsoft Excel.

В чём может быть дело. Неужели не существует способа создания корректных

Excel-файлов без использования технологии OLE и "велосипедов" вроде

экспорта StringGrid в csv-файл или Html-страницу ?
При этом использование сторонних модулей не подходит, потому что

большинство из них платные, что не устраивает заказчика, а бесплатные либо

с ограничениями вроде максимального числа строк (10-15) либо не работают в

Lazarus.

Также пробовал искать в интернете имеющийся код, пытаясь найти подробный

разбор с комментариями, но нашел лишь ссылку на первоисточник, откуда этот

код пошёл по форумам и блогам и попал в



Delphi World


(Swiss DELPHI

Center
и ссылки на западные, бразильские и турецкие форумы, где этот

код приводится как есть.

Проект на Delphi 5 во вложении.
Вложения
Тип файла: zip StringGrid_Example.zip (205.1 Кб, 24 просмотров)
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
17.09.2015, 23:02
Ответы с готовыми решениями:

Кодировка при экспорте данных в СSV-файл
Здравствуйте! Передо мной стоит задача экспорта данных в формат CSV. Я пробовал делать это...

При экспорте данных из dataGridView в файл выдается System.OutOfMemory.Exception
Есть dataGridView с данными окло 1 млн строк, нужно сохранить данные в файл. ...

Ошибки при экспорте из StringGrid в Excel
Попробовал реализовать сохранение данных из СтрингГрид в Ексель, все скомпилировалась, программа...

StringGrid, как сохранить цвет при экспорте?
Добрый день! Помогите мне пожалуйста. у меня есть stringgrid закрашиваю его так procedure...

6
600 / 548 / 210
Регистрация: 24.01.2012
Сообщений: 1,348
18.09.2015, 08:55 2
CyrillicTools в помощь. А вообще ссылки на другие форумы здесь публиковать запрещено.
0
1 / 1 / 1
Регистрация: 15.05.2014
Сообщений: 30
18.09.2015, 15:10  [ТС] 3
Цитата Сообщение от edukra Посмотреть сообщение
А вообще ссылки на другие форумы здесь публиковать запрещено.
Это было сделано с целью, чтобы не было вопросов типа "что такое Delphi World ?".
Впрочем спасибо за совет. Конечно было бы неплохо найти хороший, годный, и самое главное бесплатный компонент экспорта в Excel для Lazarus, но видимо не судьба.
Пробовал недавно экспериментировать с компонентом fpspreadsheet, но я так и не смог заставить его корректно работать - программа падает при записи данных в файл (неважно цифры, буквы, даже элементарный Hello, World), но при этом корректно создаёт пустые файлы.
0
600 / 548 / 210
Регистрация: 24.01.2012
Сообщений: 1,348
18.09.2015, 15:54 4
Только, что скачал fpspreadsheet версию 1.6 и проверил. На форму поместил TsWorksheetGrid и кнопку. в свойствах TsWorksheetGrid разрешил редактирование, а по нажатию кнопки добавил
Pascal
1
sWorksheetGrid1.SaveToSpreadsheetFile('123.xls');
Все сработало, как нужно.Записанный файл читается опенофисом правильно.
0
1 / 1 / 1
Регистрация: 15.05.2014
Сообщений: 30
18.09.2015, 17:35  [ТС] 5
А как её устанавливал ? Просто копировал файлы из архива в папку с проектом, или же в самом Lazaruse установил компонент ?

Добавлено через 3 минуты
Вот код, который я пробовал вставлять в проект - копия из официального руководства + мои дополнения (шрифт times new roman, выделение жирным, размер шрифта).

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
function SaveAsExcelFile2(AGrid: TStringGrid; AFileName: string): boolean;
//sfExcel8 - формат файла Excel 97
var
  MyWorkbook: TsWorkbook;
  MyWorksheet: TsWorksheet;
  MyDir: string;
  i,j:integer;
  float: extended; num:integer;
begin
  // Initialization
  MyDir := ExtractFilePath(ParamStr(0));
  // Create the spreadsheet
  MyWorkbook := TsWorkbook.Create;
  MyWorkbook.SetDefaultFont('Times New Roman', 12);
  //try
    MyWorksheet := MyWorkbook.AddWorksheet('My Worksheet');
    //MyWorksheet.WriteUTF8Text(1, 1, AGrid.Cells[0,0]);
    //MyWorksheet.WriteUTF8Text(1, 1, 'Hello World');
    MyWorksheet.WriteNumber(1, 3, 7.8);
 {  For i:=0 to AGrid.ColCount-1 do
    For j:=0 to AGrid.RowCount-1 do
     BEGIN
      //проверяем, является ли ячейка целым числом
      if TryStrToInt(AGrid.Cells[i,j], num) then
         begin
              MyWorksheet.WriteNumber(j, i, StrToInt(AGrid.Cells[i,j]));
         end
         //проверяем, является ли ячейка дробным числом
         else if TryStrToFloat(AGrid.Cells[i,j], float) then
         begin
         MyWorksheet.WriteNumber(j, i, StrToFloat(AGrid.Cells[i,j]));
         end
      else BEGIN MyWorksheet.WriteUTF8Text(j, i, AGrid.Cells[i,j]); END;
      MyWorksheet.WriteFont(j, i, 'Times New Roman', 12, [], AGrid.Font.Color);
      MyWorksheet.WriteColWidth(j, AGrid.colWidths[i]); //ширина столбца
     END;
   MyWorksheet.WriteFont(0, 0, 'Times New Roman', 14, [fssBold], AGrid.Font.Color);
   MyWorksheet.MergeCells(0, 0, 0, AGrid.ColCount-1);
   MyWorksheet.WriteFont(1, 0, 'Times New Roman', 14, [fssBold], AGrid.Font.Color);
   MyWorksheet.MergeCells(1, 0, 1, AGrid.ColCount-1);
   MyWorksheet.WriteFontStyle(0, 0, [fssBold]);
   MyWorksheet.WriteFontStyle(1, 0, [fssBold]);
   Myworksheet.WriteHorAlignment(0, 0, haCenter);
   Myworksheet.WriteHorAlignment(1, 0, haCenter);}
   // Save the spreadsheet to a file
   MyWorkbook.WriteToFile(MyDir + AFileName + STR_EXCEL_EXTENSION, sfExcel8, true);
   //finally
    MyWorkbook.Free;
    Result:=True;
    //end;
end;
Программа при выполнении данной функции падает,даже при записи обыкновенного числа MyWorksheet.WriteNumber(1, 3, 7.8); - в XP и семёрке просто закрывается, в windows 98 и 2000 показывает ошибку SIGSERV.

Добавлено через 3 минуты
А почему не StringGrid ?
0
600 / 548 / 210
Регистрация: 24.01.2012
Сообщений: 1,348
18.09.2015, 21:53 6
Лучший ответ Сообщение было отмечено Uncle_Sam как решение

Решение

У меня этот код работает. Осталось сравнить версии lazarus и fpspreadsheet.
На одном компе у меня lazarus 1.4 fpspreadsheet 1.6 установлен. На другом lazarus 1.2.6. fpspreadsheet не устанавливал, а просто скопировал файлы в папку с проектом. И в одном и в другом случае xls файл создался без проблем.
0
1 / 1 / 1
Регистрация: 15.05.2014
Сообщений: 30
21.09.2015, 15:23  [ТС] 7
Вобщем всё получилось, файл корректно создаётся и читается в Office 2003, 2007 и OpenOffice/LibreOffice.
Единственный недостаток это то, что при открытии документа в LibreOffice Calc в некоторых ячейках некорректно выставляется высота (когда включен автоперенос длинного текста) из-за чего отображается только последняя часть текста.

Тему можно закрывать.
0
21.09.2015, 15:23
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
21.09.2015, 15:23
Помогаю со студенческими работами здесь

При сохранении данных таблицы StringGrid в Excel появляется ошибка
При сохранении данных таблицы StringGrid в Excel появляется ошибка. Код пишу в обработчике кнопки...

Границы таблицы при экспорте в word
Здравствуйте!) у мя такая проблемка: при экспорте отчета в word (rtf) подчиненная форма (таблица)...

Форматирование поля таблицы при экспорте в dBASEIV
Нужно чтобы поле таблицы было выровнено по правому краю и вместо разделителя "," был ".".При этом...

Ошибка при экспорте таблицы DataGridView в Excel
При нажатии на кнопку выскакивает ошибка. подробности на картинке using System; using...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru