Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > [ "Начинающим" ]
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 09.02.2015, 16:02
childeroland childeroland вне форума
Прохожий
 
Регистрация: 15.04.2013
Сообщения: 21
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию Вывод дробного числа из Delphi в Excel

Здравствуйте. Целый день убил на проблему, истоки которой не могу понять. Есть код, который выводит данные из массива в диапазон ячеек Excel. Так же в коде Delphi я задаю форматирование ячеек. В одном из рядов мне необходимо использовать дробное значение вроде x.xx... Точка или запятая разделяет разряды, мне не важно. В общем, проблема типичная казалось бы, но решение мне в голову не пришло... на моей машине работает всё нормально, у меня Win7 и Excel 2007, но когда дело доходит до Win 2003 Server с его 2003 Excel, происходит что-то невероятное: разделитель дроби игнорируется, и число становится целым... Например, значение 1.83 становится при выводе в Excel числом 183 и так далее. Что я только не пробовал, менял региональные стандарты, ставил и точку и запятую в качестве разделителя, и в самом Excel международные настройки пытался использовать, ничего не помогает, с любым форматом ячеек, кроме текстового разделитель исчезает, текст использовать не могу, так как нужно считать потом данные... Под отладчиком видно, что в массив исходный пишу число с запятой (берётся из базы данных), но установка запятой в качестве разделителя не даёт результатов. Кто может помочь разобраться?
Вот несколько кусков кода моего:
1. Так я заполняю вариантный массив
Код:
begin
          Result.EmptyFlag := false;
          Result.arrCommonData := VarArrayCreate([0, 47 , 0, Params.OraQuery.FieldCount - 4], varVariant);
          for i := 0 to VarArrayHighBound(Result.arrCommonData, 1) do
            begin
              for j := 0 to VarArrayHighBound(Result.arrCommonData, 2) do
                if ((j = 43) and (Params.OraQuery.FieldCount = 50 )) or ((j = 33) and (Params.OraQuery.FieldCount = 37)) then
                  Result.arrCommonData[i,j] := Params.OraQuery.Fields.Fields[j + 3].AsFloat //[j+3] - èñêëþ÷àåì ïîëÿ 'sp.kod, sp_n1, sv.DAY_IN
                else
                  Result.arrCommonData[i,j] := Params.OraQuery.Fields.Fields[j + 3].AsInteger;
              Params.OraQuery.Next;
            end;
          Params.OraQuery.Close;
2. Так я вывожу данные
Код:
 try
    CoInitialize(nil);
    Excel := CreateOleObject('Excel.Application');
    Excel.DisplayAlerts := false;
    Excel.Visible := False;
    //Excel.UseSystemSeparators := False;
    //Excel.DecimalSeparator := ',';
  except
    //ShowMessage ('Ïðîáëåìà ïðè çàïóñêå Microsoft Excel: ïðîâåðüòå íàëè÷èå ïðîãðàììû');
  end;
  if Type_47 then
    begin
      Excel.workbooks.add(GetCurrentDir() + '\sv_47.xls');
      Sheet := Excel.WorkBooks[1].WorkSheets[1];
      Sheet.Range['B8:AV55'].Value2 := arrOut;
      Sheet.Range['B7:AV55'].NumberFormat :='0;-0;;';
      Sheet.Range['AS7:AS55'].NumberFormat :='#,##0;;;';
Давайте попробуем разобраться, а?
Ответить с цитированием
  #2  
Старый 09.02.2015, 16:29
Аватар для Alegun
Alegun Alegun вне форума
LMD-DML
 
Регистрация: 12.07.2009
Адрес: Богородское
Сообщения: 3,025
Версия Delphi: D7E
Репутация: 1834
По умолчанию

ПЧПВГ, вгонять данные в Excel как текст через FloatToStr, a получать обратно через StrToFloat
Ответить с цитированием
  #3  
Старый 09.02.2015, 16:32
childeroland childeroland вне форума
Прохожий
 
Регистрация: 15.04.2013
Сообщения: 21
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию

Цитата:
Сообщение от Alegun
ПЧПВГ, вгонять данные в Excel как текст через FloatToStr, a получать обратно через StrToFloat

а обратно мне вроде как ничего получать не надо...

и у меня данные в массиве Variant, FloatToStr тут не катит

Пробовал делать так:
Код:
for j := 0 to VarArrayHighBound(Result.arrCommonData, 2) do
                if ((j = 43) and (Params.OraQuery.FieldCount = 50 )) or ((j = 33) and (Params.OraQuery.FieldCount = 37)) then
                  Result.arrCommonData[i,j] := Params.OraQuery.Fields.Fields[j + 3].AsString
                else
                  Result.arrCommonData[i,j] := Params.OraQuery.Fields.Fields[j + 3].AsInteger;
AsString вместо AsFloat, в принципе получается примерно то же, что вы и предлагали, но всё равно разделитель просто отбрасывается

Последний раз редактировалось M.A.D.M.A.N., 09.02.2015 в 18:59.
Ответить с цитированием
  #4  
Старый 09.02.2015, 16:53
Аватар для Alegun
Alegun Alegun вне форума
LMD-DML
 
Регистрация: 12.07.2009
Адрес: Богородское
Сообщения: 3,025
Версия Delphi: D7E
Репутация: 1834
По умолчанию

Вот кстати вывод данных вариантного массива на примере из drkb
Код:
var
   ExcelApp, Workbook, Range, Cell1, Cell2, ArrayData  : Variant;
   TemplateFile : String;
   BeginCol, BeginRow, i, j : integer;
   RowCount, ColCount : integer;
begin

// Координаты левого верхнего угла области, в которую будем выводить данные
BeginCol := 1;
BeginRow := 5;

// Размеры выводимого массива данных
RowCount := 100;
ColCount := 50;

// Создание Excel
ExcelApp := CreateOleObject('Excel.Application');

// Отключаем реакцию Excel на события, чтобы ускорить вывод информации
ExcelApp.Application.EnableEvents := false;

//  Создаем Книгу (Workbook)
//  Если заполняем шаблон, то Workbook := ExcelApp.WorkBooks.Add('C:\MyTemplate.xls');

Workbook := ExcelApp.WorkBooks.Add;

// Создаем Вариантный Массив, который заполним выходными данными
ArrayData := VarArrayCreate([1, RowCount, 1, ColCount], varVariant);

// Заполняем массив
for I := 1 to RowCount do
   for J := 1 to ColCount do
     ArrayData[I, J] := J * 10 + I;

// Левая верхняя ячейка области, в которую будем выводить данные
Cell1 := WorkBook.WorkSheets[1].Cells[BeginRow, BeginCol];
// Правая нижняя ячейка области, в которую будем выводить данные
Cell2 := WorkBook.WorkSheets[1].Cells[BeginRow  + RowCount - 1, BeginCol +
ColCount - 1];

// Область, в которую будем выводить данные
Range := WorkBook.WorkSheets[1].Range[Cell1, Cell2];

// А вот и сам вывод данных
// Намного быстрее поячеечного присвоения
Range.Value := ArrayData;

// Делаем Excel видимым
ExcelApp.Visible := true;
Ответить с цитированием
  #5  
Старый 09.02.2015, 16:59
childeroland childeroland вне форума
Прохожий
 
Регистрация: 15.04.2013
Сообщения: 21
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию

Хех =) спасибо, конечно, но как вывести вариантный массив в Excel я знаю, собственно, у меня так же и есть. Вопрос-то не в этом, вопрос в том, что у меня неправильно на одной (а возможно и не на одной) машине выводятся данные... причём сильно неправильно, это даже погрешностью назвать нельзя, когда 1.83 становится 183, а общая сумма из 43.5 превращается в 1000... Дело не в форматах, все форматы я перепробовал, пробовал вообще без форматов, результат один и тот же
Ответить с цитированием
  #6  
Старый 09.02.2015, 17:14
Аватар для Alegun
Alegun Alegun вне форума
LMD-DML
 
Регистрация: 12.07.2009
Адрес: Богородское
Сообщения: 3,025
Версия Delphi: D7E
Репутация: 1834
По умолчанию

Оффтоп: Только что проверил этот код с дробным массивом - в 2003 Excel данные выводит правильно
Ответить с цитированием
  #7  
Старый 09.02.2015, 18:40
childeroland childeroland вне форума
Прохожий
 
Регистрация: 15.04.2013
Сообщения: 21
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию

Цитата:
Сообщение от Alegun
Оффтоп: Только что проверил этот код с дробным массивом - в 2003 Excel данные выводит правильно

Везёт)... А я со своей стороны в VBA в ячейки под разными форматами записывал дробные числа и с запятой и с точкой, тоже всё нормально, хотя я встречал в интернете инфу о том, что как раз VBA с Excel работает идеально, а вот дельфи подтупливает... Прихожу к выводу, что 2003 Excel здесь ни причём, дело скорее всего в том, как представляет дробные числа Win2003... хотя это конечно бред... т. е., проблема в связке моей программы и винды... но вот как понять, в чём именно...
Ответить с цитированием
  #8  
Старый 09.02.2015, 19:58
Аватар для Alegun
Alegun Alegun вне форума
LMD-DML
 
Регистрация: 12.07.2009
Адрес: Богородское
Сообщения: 3,025
Версия Delphi: D7E
Репутация: 1834
По умолчанию

Больше похоже на "косяки" БД-провайдера, - а точно ли массив заполняется нужными числами, хорошо бы под наладкой это проверить. Я пробовал и дроби и текст загонять в Excel: загоняются, дроби правда сразу в денежный формат перетекают, а вот текст нормально отображается, см. наполнение массива
Ответить с цитированием
Этот пользователь сказал Спасибо Alegun за это полезное сообщение:
childeroland (09.02.2015)
  #9  
Старый 09.02.2015, 21:34
childeroland childeroland вне форума
Прохожий
 
Регистрация: 15.04.2013
Сообщения: 21
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию

Цитата:
Сообщение от Alegun
Больше похоже на "косяки" БД-провайдера, - а точно ли массив заполняется нужными числами, хорошо бы под наладкой это проверить. Я пробовал и дроби и текст загонять в Excel: загоняются, дроби правда сразу в денежный формат перетекают, а вот текст нормально отображается, см. наполнение массива

Проверить тяжело, ибо, по непонятным мне причинам, вариантные массивы в Delphi7 под отладчиком просмотреть нельзя (по крайней мере я не знаю как)... точно могу посмотреть, какие числа возвращает SQL, там всё в порядке... Да и потом, на других машинах всё нормально, значит в массиве то, что нужно... Конкретно проблема проявилась на Excel 2003 и Windows2003 Server, на том же офисе (скорее всего на том же, но точно до версии сказать не могу), но на WinXP отображение правильное...
Не знаю, попробовать что ли поставить делфю на сервер и там запустить отладчик... Хотя нет, туплю, проще лог сделать на предмет того, что из базы возвращается на той машине...

Про БД-провайдер совет дельный, работаю на Oracle, и версии клиента скорее всего разные... Вот какая на XP стоит, я не уверен, покопаюсь в этой теме
Ответить с цитированием
  #10  
Старый 09.02.2015, 22:14
childeroland childeroland вне форума
Прохожий
 
Регистрация: 15.04.2013
Сообщения: 21
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию

Цитата:
Сообщение от Alegun
Больше похоже на "косяки" БД-провайдера, - а точно ли массив заполняется нужными числами, хорошо бы под наладкой это проверить. Я пробовал и дроби и текст загонять в Excel: загоняются, дроби правда сразу в денежный формат перетекают, а вот текст нормально отображается, см. наполнение массива


Вот спасибо!!! Дело действительно в провайдере, или, может быть, в клиенте Oracle, это мне ещё предстоит выяснить более подробно и придумать красивые пути решения, ибо я извращенец и люблю доводить такие вещи до почти совершенства...
На данном этапе смог получить нужного результата путём добавления параметра NLS_NUMERIC_CHARACTERS, равного ".," (точка и запятая) в ветку реестра HKLM\Software\Oracle\HOMEx, где HOMEx - номер дома Oracle. (мало ли, вдруг кому пригодится). Снизу ссылка на форум, где я это нашёл.

http://www.sql.ru/forum/305991/probl...er-prilozhenii

Но наверняка это можно настроить в дельфовом провайдере (использую dbExpress)...
А тебе огромное спасибо!
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 23:42.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter