Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2013.03.22;
Скачать: [xml.tar.bz2];

Вниз

Экспорт в Excel2010: значения NumberFormat ячейки   Найти похожие ветки 

 
AlekVolsk   (2011-05-01 12:16) [0]

Доброго времени суток.
Значения чисел, дробных чисел, даты и времеи, а также чисел длиною более 19 знаков, переданные в качестве строки (string), передаются криво: ячейка содержит значение 64. Какой NumberFormat необходимо выставить ячейкам, чтобы данные передавались корректно? В более ранних версиях Excel достаточно было указать "@", в 2010 это не работает. Спасибо.


 
AlekVolsk   (2011-05-04 01:14) [1]

Опытным путем (Установка формата в книге вручную и чтение NumberFormat программно) установил:
 @ - текст
 Основной - общий
 0 - числовой
 0,00 - числовой
 # ##0,00 - числовой с разделителем
 ДД.ММ.ГГГГ - дата
 чч:мм:сс;@ - время

Однако, если я программно учтанавливаю любое из этих значений, то по факту записывается значение 64:
var
 xls, wb: OLEVariant;
begin
 try xls := GetActiveOleObject("Excel.Application");
 except xls := CreateOleObject("Excel.Application");
 end;
 wb := xls.Workbooks.Add;
 // ...
 wb.WorkSheets[1].Cells[1, 1].NumberFormat := "@";
 wb.WorkSheets[1].Cells[1, 1].Value := 1528.26;
 // ...
end;


Cell[1, 1] содержит формат 64, отображаемое значение в строке формул 1528.26, отображаемое значение в ячейке 64. Почему? Что я делаю не так? В Excel с 2000 по 2007 все работает на отлично!


 
sniknik ©   (2011-05-04 07:53) [2]

> Опытным путем
а как же обычное - записать макрос и посмотреть?

> wb.WorkSheets[1].Cells[1, 1].Value := 1528.26;
а как макрос в 2010м вносит значения? в 2003м не через Value, а через FormulaR1C1. и так думаю правильней, но не лишнее бы и посмотреть в макрос. научится пользоваться.


 
OW ©   (2011-05-04 10:09) [3]


> Установка формата в книге вручную и чтение NumberFormat
> программно

А еще надо NumberFormatLocal  смотреть/ ставить

FormatSheet(ActiveSheets, 2, 5, RowCount, 5, "#,##0", "# ##0,00");

procedure FormatSheet(Sheet: Variant; BR, BC, ER, EC: Integer; Formats, FormatsLocal: string);
var
 Range, C1, C2: Variant;
begin
 C1 := Sheet.Cells[BR, BC];
 C2 := Sheet.Cells[ER, EC];
 Range := Sheet.Range[C1, C2];
 if Formats <> "" then
   Range.NumberFormat := Formats;
 if FormatsLocal <> "" then
   Range.NumberFormatLocal := FormatsLocal;
end;


 
sniknik ©   (2011-05-04 14:10) [4]

> А еще надо NumberFormatLocal  смотреть/ ставить
зачем если по формату от присваивает строку... типа обязуется, но после правда вносит число.
> wb.WorkSheets[1].Cells[1, 1].NumberFormat := "@";
> wb.WorkSheets[1].Cells[1, 1].Value := 1528.26;
правильнее было бы так
wb.WorkSheets[1].Cells[1, 1].NumberFormat := "@";
wb.WorkSheets[1].Cells[1, 1].Value := "1528.26";


 
sniknik ©   (2011-05-04 14:11) [5]

> правильнее было бы так
вернее, еще правильнее, так как макрос генерит, т.е. через FormulaR1C1


 
AlekVolsk   (2011-05-04 19:12) [6]

Я с макросами на vba не очень дружен, к тому же просто очень поверхностно знаком с устройством Excel, мне просто нужно:
1. вывести данные с грида в книгу, с шапкой;
2. по заполненым ячейкам выставить границы;
3. шапку сделать болдом;
4. заполненым колонкам сделать AutoFit.
В гриде переменное кол-во полей/записей сог-но настройкам/фильтрам конечного пользователя.
Я не знаю куда залезьть, посмотреть пример, как передать через FormulaR1C1.
Пока строковые значения передаю как
wb.WorkSheets[1].Cells[1, 1].Value := """" + 1528.26;
хотя это и не совсем правильно.


 
sniknik ©   (2011-05-04 19:34) [7]

> Я не знаю куда залезьть, посмотреть пример, как передать через FormulaR1C1.
http://www.google.ru/search?q=%D0%B7%D0%B0%D0%BF%D0%B8%D1%81%D1%8C+%D0%BC%D0%B0%D0%BA%D1%80%D0%BE%D1%81%D0%B0+%D0%B2+excel&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:ru:official&client=firefox

> хотя это и не совсем правильно.
совсем не правильно, даже не скомпилируется...
а вот так вполне нормально
wb.WorkSheets[1].Cells[1, 1].Value := """1528.26";


 
AlekVolsk   (2011-05-05 11:57) [8]

А ларчик-то просто открывался: Unicode!
Вместе с обновлением офиса до 2010 я обновил Delphi с 2006 до XE. а он на юникоде весь! т.е. годда я передаю символ @, это еще не значит что я передаю непосредственно символ с кодом #64, т.к. в русской локализации символ @ имеет код аж восемьсот-какой-то (непомню точно).
Обнаружил, когда пересобрал проект снова на D2006, все данные в Excel2010 перекатывались на отлично. Тут-то я и вспомнил про юникод...

wb.WorkSheets[1].Cells[1, 1].NumberFormat := #64;


 
Anatoly Podgoretsky ©   (2011-05-05 12:09) [9]

> AlekVolsk  (05.05.2011 11:57:08)  [8]

Это значит что ты вводил символ в другой кодировке и поленился исправить
его.


 
sniknik ©   (2011-05-05 12:10) [10]

> обновил Delphi с 2006 до XE
вот для этого и существует в создании вопроса галочка, или поле если нету, версии дельфей.
спартизанил, вот и помучился.


 
AlekVolsk   (2011-05-06 17:14) [11]

Кому интересно:

unit to_excel;

interface

uses cxGridDBTableView;

procedure GridToMSExcel(Grid: TcxGridDBTableView);

implementation

uses
 COMObj, ShlObj, ActiveX, Variants, Forms, DB, Dialogs;

const
 // Vertical alignment
 xl_VCenterAlignment = 2;

 // Hirizontal alignment
 xl_HLeftAlignment = 2;
 xl_HCenterAlingment = 3;
 xl_HRightAlignment = 4;

 // Borders
 xlEdgeLeft = 1;
 xlEdgeRight = 2;
 xlEdgeTop = 3;
 xlEdgeBottom = 4;
 xlInsideVertical = 11;
 xlInsideHorizontal = 12;
 xlDiagonalDown = 5;
 xlDiagonalUp = 6;

 // Line style
 xlNone = 0; // отсутствует
 xlContinuous = 1; // обычная
 xlDash = 2; // пунктир
 xlDot = 3; //пунктир точками
 xlDashDot = 4; // пунктир с точкой
 xlDashDotDot = 5; // пунктир с двумя точками
 xlSlantDashDot = 6; // пунктир со скошенной точкой
 xlDouble = $FFFFEFE9; // двойная

 // Line weight - толщина линии
 xlHairline = 1; // тонкая прерывистая, очень тонкий пунктир, LineStyle := xlContinuous;
 xlThin = 2; // стандартная
 xlMedium = 3; // толстая
 xlThick = 4; // очень толстая

function ITS(I: integer): string;
var
 S: shortstring;
begin
 try
   Str(I, S);
   Result := string(S);
 except Result := "";
 end;
end;

function BooleanToStr(Value: boolean): string;
begin
 Result := "Нет";
 if Value then Result := "Да";
end;

function GetIC(Value: integer): string;
{ Возвращает строковое представление порядкового номера заголовка столбца в MS Excel }
var
 x, y: integer;
begin
 Result := "";
 case Value of
   1..26: Result := Result + Chr(Value + 64);
   27..702: begin
     x := Value div 26;
     y := Value mod 26;
     Result := Result + Chr(x + 64);
     Result := Result + Chr(y + 64);
   end;
 end;
end;

function IsOLEObjectInstalled(OLEName: string): boolean;
{ Проверяет, запущен ли сервер автоматизации }
var
 ClassID: TGUID;
begin
 Result := CLSIDFromProgID(PWideChar(WideString(OLEName)), ClassID) = S_OK;
end;

procedure GridToMSExcel(Grid: TcxGridDBTableView);
{ Экспорт сетки данных в MS Excel }
var
 xls, wb: OLEVariant;
 col, row, cols, rows, coli, rowi: integer;
 s: string;
 ArrayData, v: variant;
begin
 cols := Grid.VisibleColumnCount;
 rows := Grid.DataController.RowCount;
 if rows = 0 then begin
   ShowMessage("Количество экспортируемых строк равно 0. Вы не можете экспортировать пустой НД.");
   exit;
 end;
 if rows > 65500 then begin
   ShowMessage("Вы пытаетесь экспортировать " + ITS(rows) + " строк. Кол-ов экспортируемых строк не должно превышать 65500. Экспорт данных невозможен.");
   exit;
 end;
 if not IsOLEObjectInstalled("Excel.Application") then begin
   ShowMessage("Не удалось обнаружить на Вашем компьютере установленный MS Excel. Экспорт данных невозможен.");
   exit;
 end;
 try xls := GetActiveOleObject("Excel.Application");
 except xls := CreateOleObject("Excel.Application");
 end;
 wb := xls.Workbooks.Add;

 for col := 1 to cols do begin
   wb.WorkSheets[1].Cells[1, col].Value := Grid.VisibleColumns[pred(col)].Caption;
   s := GetIC(col);
   s := s + ":" + s;
   xls.Range[s].Select;
   case Grid.DataController.DataSet.FieldByName((Grid.VisibleColumns[pred(col)] as TcxGridDBColumn).DataBinding.FieldName).DataType of
     ftString, ftMemo, ftFixedChar, ftWideString, ftFmtMemo, ftWideMemo, ftBoolean: s := #64;
     ftDate, ftDateTime, ftTimeStamp: s := "ДД.ММ.ГГГГ";
     ftTime: s := "чч:мм:сс;@";
     ftBCD, ftFloat, ftCurrency: s := "# ##0,00";
   else s := "# ##0";
   end;
   xls.Selection.NumberFormat := s;
   xls.Selection.NumberFormatLocal := s;
   Application.ProcessMessages;
 end;

 ArrayData := VarArrayCreate([1, rows, 1, cols], varVariant);
 for row := 1 to rows do begin
   rowi := Grid.ViewData.Rows[pred(row)].RecordIndex;
   for col := 1 to cols do begin
     coli := Grid.VisibleColumns[pred(col)].Index;
     v := Grid.DataController.Values[rowi, coli];
     case Grid.DataController.DataSet.FieldByName((Grid.VisibleColumns[pred(col)] as TcxGridDBColumn).DataBinding.FieldName).DataType of
       ftString, ftMemo, ftFixedChar, ftWideString, ftFmtMemo, ftWideMemo: ArrayData[row, col] := VarToStr(v);
       ftBoolean: ArrayData[row, col] := BooleanToStr(v);
     else ArrayData[row, col] := v;
     end;
     Application.ProcessMessages;
   end;
   Application.ProcessMessages;
 end;
 s := "A2:" + GetIC(cols) + ITS(rows + 1);
 xls.Range[s].Value := ArrayData;

 xls.Range[s].Select;
 xls.Selection.Borders[xlEdgeLeft].LineStyle := xlContinuous;
 xls.Selection.Borders[xlEdgeLeft].Weight := xlMedium;
 xls.Selection.Borders[xlEdgeRight].LineStyle := xlContinuous;
 xls.Selection.Borders[xlEdgeRight].Weight := xlMedium;
 xls.Selection.Borders[xlEdgeBottom].LineStyle := xlContinuous;
 xls.Selection.Borders[xlEdgeBottom].Weight := xlMedium;
 xls.Selection.Borders[xlInsideVertical].LineStyle := xlContinuous;
 xls.Selection.Borders[xlInsideVertical].Weight := xlThin;
 xls.Selection.Borders[xlInsideHorizontal].LineStyle := xlContinuous;
 xls.Selection.Borders[xlInsideHorizontal].Weight := xlThin;

 s := "A1:" + GetIC(cols) + "1";
 xls.Range[s].Select;
 xls.Selection.Borders[xlEdgeLeft].LineStyle := xlContinuous;
 xls.Selection.Borders[xlEdgeLeft].Weight := xlMedium;
 xls.Selection.Borders[xlEdgeRight].LineStyle := xlContinuous;
 xls.Selection.Borders[xlEdgeRight].Weight := xlMedium;
 xls.Selection.Borders[xlEdgeTop].LineStyle := xlContinuous;
 xls.Selection.Borders[xlEdgeTop].Weight := xlMedium;
 xls.Selection.Borders[xlEdgeBottom].LineStyle := xlDouble;
 xls.Selection.Borders[xlEdgeBottom].Weight := xlThick;
 xls.Selection.Borders[xlInsideVertical].LineStyle := xlContinuous;
 xls.Selection.Borders[xlInsideVertical].Weight := xlThin;

 xls.Range["1:1"].Select;
 xls.Selection.Font.Bold := true;
 xls.Selection.VerticalAlignment := xl_VCenterAlignment;
 xls.Selection.HorizontalAlignment := xl_HCenterAlingment;
 xls.Selection.NumberFormat := #64;
 xls.Selection.NumberFormatLocal := #64;

 s := "A:" + GetIC(cols);
 xls.Range[s].Select;
 xls.Selection.Columns.AutoFit;
 wb.WorkSheets[1].PageSetup.LeftMargin := 25;   // 2.5 единицы Excel = 1 миллиметр
 wb.WorkSheets[1].PageSetup.RightMargin := 25;
 wb.WorkSheets[1].PageSetup.TopMargin := 25;
 wb.WorkSheets[1].PageSetup.BottomMargin := 25;

 xls.Cells[1, 1].Select;
 xls.Visible := true;
 ArrayData := null;
 wb := null;
 xls := null;
 HideProgress;
end;

end.


 
AlekVolsk   (2011-05-12 10:36) [12]

Кому интересно, аналогичная ф-ция для ОО. Не знаю, как сделать border"ы ячеек, пытался сделать по образцу, взятому там: http://www.sql.ru/forum/actualthread.aspx?tid=405083 , не получилось.

unit kd_odc;

interface

uses cxGridDBTableView;

procedure GridToOdc(Grid: TcxGridDBTableView);

implementation

uses
 COMObj, ShlObj, ActiveX, Variants, Forms, DB, SysUtils, Dialogs;

function BooleanToStr(Value: boolean): string;
begin
Result := "Нет";
if Value then Result := "Да";
end;

function IsOLEObjectInstalled(OLEName: string): boolean;
{ Проверяет, запущен ли сервер автоматизации }
var
 ClassID: TGUID;
begin
 Result := CLSIDFromProgID(PWideChar(WideString(OLEName)), ClassID) = S_OK;
end;

procedure GridToOdc(Grid: TcxGridDBTableView);
{ Экспорт сетки данных в OpenOffice.org/LibreOffice.org }
var
 oo, coreprop, corepropitem, calc, tbl, fmt, tmp, sheets, sheet: OLEVariant;
 col, row, cols, rows, coli, rowi,
   fmt_string, fmt_date, fmt_time, fmt_integer, fmt_currency: integer;
 v: variant;
begin
 cols := Grid.VisibleColumnCount;
 rows := Grid.DataController.RowCount;
 if cols = 0 then begin
   ShowMessage("Количество экспортируемых столбцов равно 0. Вы не можете экспортировать пустой НД.");
   exit;
 end;
 if rows = 0 then begin
   ShowMessage("Количество экспортируемых строк равно 0. Вы не можете экспортировать пустой НД.");
   exit;
 end;
 if rows > 65500 then begin
   ShowMessage("Вы пытаетесь экспортировать " + ITS(rows) + " строк. Кол-ов экспортируемых строк не должно превышать 65500. Экспорт данных невозможен.");
   exit;
 end;
 if not IsOLEObjectInstalled("com.sun.star.ServiceManager") then begin
   ShowMessage("Не удалось обнаружить на Вашем компьютере установленный OpenOffice.org/LibreOffice.org. Экспорт данных невозможен.");
   exit;
 end;
 try oo := GetActiveOleObject("com.sun.star.ServiceManager");
 except oo := CreateOleObject("com.sun.star.ServiceManager");
 end;
 calc := oo.CreateInstance("com.sun.star.frame.Desktop");
 coreprop := VarArrayCreate([0, 0], VarVariant);
 corepropitem := calc.Bridge_GetStruct("com.sun.star.beans.PropertyValue");
 corepropitem.Name := "Hidden";
 corepropitem.Value := true;
 coreprop[0] := corepropitem;
 tbl := calc.LoadComponentFromURL("private:factory/scalc","_blank", 0, coreprop);
 tbl.getCurrentController.getFrame.getContainerWindow.setVisible(false);
 sheets := tbl.getSheets;
 sheet := sheets.getByIndex(0);

 tmp := tbl.GetNumberFormats;
 fmt := oo.Bridge_GetStruct("com.sun.star.lang.Locale");
 fmt_string := tmp.QueryKey(#64, fmt, false);
 if fmt_string < 0 then fmt_string := tmp.AddNew(#64, fmt);
 fmt_date := tmp.QueryKey("DD.MM.YYYY", fmt, false);
 if fmt_date < 0 then fmt_date := tmp.AddNew("DD.MM.YYYY", fmt);
 fmt_time := tmp.QueryKey("HH:MM:SS", fmt, false);
 if fmt_time < 0 then fmt_time := tmp.AddNew("HH:MM:SS", fmt);
 fmt_integer := tmp.QueryKey("# ##0", fmt, false);
 if fmt_integer < 0 then fmt_integer := tmp.AddNew("# ##0", fmt);
 fmt_currency := tmp.QueryKey("# ##0.00", fmt, false);
 if fmt_currency < 0 then fmt_currency := tmp.AddNew("# ##0.00", fmt);

 for col := 0 to pred(cols) do begin
   sheet.GetCellByPosition(col, 0).NumberFormat := fmt_string;
   sheet.GetCellByPosition(col, 0).SetString(Grid.VisibleColumns[col].Caption);
   sheet.GetCellByPosition(col, 0).getText.createTextCursor.CharWeight := 150;
   Application.ProcessMessages;
 end;
 for row := 0 to pred(rows) do begin
   rowi := Grid.ViewData.Rows[row].RecordIndex;
   for col := 0 to pred(cols) do begin
     coli := Grid.VisibleColumns[col].Index;
     v := Grid.DataController.Values[rowi, coli];
     case VarType(v) of
       varString, varOleStr, varUString, varStrArg, varEmpty, varNull: begin
         sheet.GetCellByPosition(col, row + 1).NumberFormat := fmt_string;
         sheet.GetCellByPosition(col, row + 1).SetString(VarToStr(v));
       end;
       varDate: begin
         if (VarToDateTime(v) < 30000) and (VarToDateTime(v) >= 1) then sheet.GetCellByPosition(col, row + 1).NumberFormat := fmt_time else sheet.GetCellByPosition(col, row + 1).NumberFormat := fmt_date;
         sheet.GetCellByPosition(col, row + 1).SetValue(VarToDateTime(v));
       end;
       varBoolean: begin
         sheet.GetCellByPosition(col, row + 1).NumberFormat := fmt_string;
         sheet.GetCellByPosition(col, row + 1).SetString(BooleanToStr(v));
       end;
       varSmallint, varShortInt, varInteger, varInt64, varUInt64, varWord, varLongWord, varByte: begin
         sheet.GetCellByPosition(col, row + 1).NumberFormat := fmt_integer;
         sheet.GetCellByPosition(col, row + 1).SetValue(v);
       end;
       varSingle, varDouble, varCurrency: begin
         sheet.GetCellByPosition(col, row + 1).NumberFormat := fmt_currency;
         sheet.GetCellByPosition(col, row + 1).SetValue(v);
       end;
     end;
   end;
   Application.ProcessMessages;
 end;

 for col := 0 to pred(cols) do begin
   sheet.getColumns.getByIndex(col).setPropertyValue("OptimalWidth", true);
   sheet.GetCellByPosition(col, 0).HoriJustify := 2;
   Application.ProcessMessages;
 end;

 tbl.getCurrentController.getFrame.getContainerWindow.setVisible(true);
 tmp := Unassigned;
 fmt := Unassigned;
 sheet := Unassigned;
 sheets := Unassigned;
 tbl := Unassigned;
 calc := Unassigned;
 corepropitem := Unassigned;
 coreprop := Unassigned;
 oo := Unassigned;
end;

end.



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2013.03.22;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.52 MB
Время: 0.062 c
15-1344601216
Павел
2012-08-10 16:20
2013.03.22
установка


2-1328882938
Сергей
2012-02-10 18:08
2013.03.22
SimpleDataSet как обновить данные?


15-1344860028
IGray
2012-08-13 16:13
2013.03.22
Автоматизация обновления Indy10 для Delphi 2009


2-1332071987
Pcrepair
2012-03-18 15:59
2013.03.22
компонент TIdHTTP, разница в синтаксисе для ИНДИ7 и ИНДИ10


15-1349873116
RTF
2012-10-10 16:45
2013.03.22
Сжать график.





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский