Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2013.03.22;
Скачать: CL | DM;

Вниз

Экспорт в 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;
Скачать: CL | DM;

Наверх




Память: 0.54 MB
Время: 0.063 c
2-1330505116
AlexDn
2012-02-29 12:45
2013.03.22
if....then.....


15-1353474231
Бумбум
2012-11-21 09:03
2013.03.22
Как выделить числа в календаре


6-1257159963
tlm
2009-11-02 14:06
2013.03.22
Webbrowser и координаты мыши


15-1346305970
ZeroDivide
2012-08-30 09:52
2013.03.22
Современный смартфон с долгой батарейкой. Есть такие?


15-1338928202
Юрий
2012-06-06 00:30
2013.03.22
С днем рождения ! 6 июня 2012 среда