Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: ActiveX/СОМ/CORBA > export from excel - delphi


Автор: Sed0Y 25.2.2010, 23:49
Добрый день.

У меня есть документ Ексель, в нем какие-то значения к примеру


Код

    А             В
1 ------пусто-------
2 Тарелки     20
3 кирьпичь    2000
4 цемент       5
5 ------пусто-------
6 ------пусто-------


этот документ постоянно редактируется в бухгалтерии, а мне нужно получать данные с него, к себе на форму, то как с Делфи мне считать дынные с этого документа что бы небыло ситуации закрытия документа или какой-то ошибки.... я делаю это так:

Код

.....
TYPE
     XLApp: TExcelApplication;
.....
var
  WorkBk: _WorkBook;
  WorkSheet: _WorkSheet;
  K, R, X, Y: Integer;
  sec, min, hour: Integer;
  IIndex: OleVariant;
  RangeMatrix: Variant;
  NomFich: WideString;
begin
  NomFich := 'C:\123.xls';
  IIndex := 1;
  XLApp.Connect; 
  XLApp.WorkBooks.Open(NomFich, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam,
  EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, 0);
  WorkBk := XLApp.WorkBooks.Item[IIndex];
  WorkSheet := WorkBk.WorkSheets.Get_Item(1) as _WorkSheet;
  WorkSheet.Cells.SpecialCells(xlCellTypeLastCell,EmptyParam).Activate;
  X := XLApp.ActiveCell.Row;
  Y := XLApp.ActiveCell.Column;
  StringGrid.ColCount := Y;
  RangeMatrix := XLApp.Range['A1', XLApp.Cells.Item[X,Y]].Value2;
  XLApp.Quit;
  K := 1;
  repeat
    for R := 1 to Y do
      StringGrid.Cells[(R - 1),(K - 1)] := RangeMatrix[K,R];
    Inc(K,1);
    StringGrid.RowCount := K + 1;
  until
    K > X;
  RangeMatrix := Unassigned;




xlapp.connect; // если в документе сделали изменение но не сохранили то на этом месте происходит ошибка - то как считать данные без сохранение, то есть если изменили данные на листе и не сохранили то все равно мы сумели считать эти изменения не сохраняя документ?

xlapp.quit; // в таком случае, если документ открыт, то он закрывается а если это убрать и документ будет закрыт, то после закрытия программы будет в процессах висеть процесс екселя

Короче говоря как считать с документа открытого другим пользователем на редактирование данные которые небыли сохранены (в документе)?

Автор: Данкинг 26.2.2010, 00:17
Файл расшаренный и лежит на серваке, что ли? Тогда каким образом "xlapp.quit;" может закрывать документ, открытый на другом компе? smile  

Цитата(Sed0Y @  25.2.2010,  23:49 Найти цитируемый пост)
Короче говоря как считать с документа открытого другим пользователем на редактирование данные которые небыли сохранены (в документе)? 

Думаю, что никак. Если только каким-то образом сохранять копию файла и её уже считывать.

Автор: Sed0Y 26.2.2010, 03:04
значит не стал париться и заморачиваться с XLApp.WorkBooks переделал на получение данных с ексель листа через АДО и выгружаю в Грид

только вот столкнулся с проблемкой не могу решить
первая строка в екселе экспортируется в рид как название Титла, что сделать что бы содержимое Листа было в гриде а не в залазило и в шапку (см. рисунок)? 

user posted image

сделал экспорт так:
Код

procedure TFMain.ConnectToExcel;
var
  strConn: widestring;
begin
  strConn := 'Provider=Microsoft.Jet.OLEDB.4.0;' +
          'Data Source=' + FilePatch + ';' +
          'Extended Properties=Excel 8.0;';
  AdoConnection1.Connected := False;
  AdoConnection1.ConnectionString := strConn;
  try
    AdoConnection1.Open;
  except
    ShowMessage('не могу соединиться с ексель книгой: ' + FilePatch + ' !');
  raise;
  end
end;

procedure TFMain.FetchData;
var
  i: Integer;
begin
  ConnectToExcel;
  AdoQuery1.Close;
  AdoQuery1.SQL.Text := Edit2.Text ; // SELECT * FROM [Лист1$]
  try
    AdoQuery1.Open;
  except
    ShowMessage( 'Не могу выполнить СКЛ запрос ' + Edit2.Text +'!');
  raise;
  end;

  for i := 0 to DBGridEh1.Columns.Count -1 do
    DBGridEh1.Columns.Items[i].Width := 100  
end;


procedure TFMain.Button1Click(Sender: TObject);
begin
  FetchData
end;




Автор: dimaximo 25.4.2010, 13:10
Здравствуйте! Может кто сталкивался с этим, помогите, пожалуйста, решить проблемку. Использовал ниже представленный код для экспорта данных из Excel. Проблема в том,что тип данных "время" и в stringGridе,после перемещения отображаются в вещественном типе. Как можно из вещест.типа сделать тип время? smile   
Код

.....
TYPE
     XLApp: TExcelApplication;
.....
var
  WorkBk: _WorkBook;
  WorkSheet: _WorkSheet;
  K, R, X, Y: Integer;
  sec, min, hour: Integer;
  IIndex: OleVariant;
  RangeMatrix: Variant;
  NomFich: WideString;
begin
  NomFich := 'C:\123.xls';
  IIndex := 1;
  XLApp.Connect; 
  XLApp.WorkBooks.Open(NomFich, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam,
  EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, 0);
  WorkBk := XLApp.WorkBooks.Item[IIndex];
  WorkSheet := WorkBk.WorkSheets.Get_Item(1) as _WorkSheet;
  WorkSheet.Cells.SpecialCells(xlCellTypeLastCell,EmptyParam).Activate;
  X := XLApp.ActiveCell.Row;
  Y := XLApp.ActiveCell.Column;
  StringGrid.ColCount := Y;
  RangeMatrix := XLApp.Range['A1', XLApp.Cells.Item[X,Y]].Value2;
  XLApp.Quit;
  K := 1;
  repeat
    for R := 1 to Y do
      StringGrid.Cells[(R - 1),(K - 1)] := RangeMatrix[K,R];
    Inc(K,1);
    StringGrid.RowCount := K + 1;
  until
    K > X;
  RangeMatrix := Unassigned;


Автор: Albinos_x 25.4.2010, 14:57
проверяй форматирование ячейки в excel, если формат ячейки типа даты/время, значение перез занесением в форму приводи к нужному типу...

Автор: dimaximo 25.4.2010, 16:29
Как можно поверить? Я в этом деле новичок, буду бесконечно благодарен за листинг smile ...

Автор: Albinos_x 26.4.2010, 09:12
проверить или написать конкретный код мне сейчас негде, но приблизительно так будет выглядить проверка на формат, через range:
Код

if (XLApp.Range['A1',EmptyParam].NumberFormat='dd/mm/yy h:mm;@') or
   (XLApp.Range['A1',EmptyParam].NumberFormat='h:mm;@') then
   ......

как это прикрутить или использовать применительно к твоему коду думаю тебе не составит труда. 
удачи

Автор: dimaximo 26.4.2010, 12:15
спс болшое smile Попробую сделать

Автор: dimaximo 27.4.2010, 15:23
Albinos_x, 
Подскажите, пожалуйста, для чего нужен символ '@' и как можно сохранить данные о времени в stringGrid в том виде в котором они находятся в Excel...

Автор: Albinos_x 27.4.2010, 20:38
Цитата(dimaximo @  27.4.2010,  15:23 Найти цитируемый пост)
Подскажите, пожалуйста, для чего нужен символ '@'

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

Цитата(dimaximo @  27.4.2010,  15:23 Найти цитируемый пост)
как можно сохранить данные о времени в stringGrid в том виде в котором они находятся в Excel.

в экселе много представлений даты/времени... какой именно интересует тебя?

Автор: dimaximo 28.4.2010, 14:16
Цитата

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

понятно smile ...
меня интересует форма представления времени "h:mm". Данные в формате "h:mm" считываются из Excel и заносятся в StringGrid уже в вещественном виде от 0...0,99. 
Код

RangeMatrix := XLApp.Range['A1', XLApp.Cells.Item[X,Y]].Value2;
  K := 1;
  repeat
    for R := 1 to Y do
      StringGrid.Cells[(R - 1),(K - 1)] := RangeMatrix[K,R];
    Inc(K,1);
    StringGrid.RowCount := K + 1;
  until
    K > X;

То условие 
Код

if (XLApp.Range['A1',EmptyParam].NumberFormat='dd/mm/yy h:mm;@') or
   (XLApp.Range['A1',EmptyParam].NumberFormat='h:mm;@') then
   ......

что вы написали,я как понимаю,можно использовать для проверки ячейки в Excel на формат представления для её последующего форматирования. Может быть есть такое решение,которое преобразует "время" в вещественной форме обратно в "h:mm"

Автор: Albinos_x 28.4.2010, 15:21
Цитата(dimaximo @  28.4.2010,  14:16 Найти цитируемый пост)
 Данные в формате "h:mm" считываются из Excel и заносятся в StringGrid уже в вещественном виде от 0...0,99. 

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

var t:String;
...
DateTimeToString( S, 'hh:mm', RangeMatrix[K,R]);


Добавлено через 2 минуты и 38 секунд
Цитата(dimaximo @  28.4.2010,  14:16 Найти цитируемый пост)
 для проверки ячейки в Excel на формат представления для её последующего форматирования

время в компе храниться в вечестрвенном виде... целая часть - это сутки, дробная - время. Поэтому в любом случае перед выводом нужно использовать команды преобразования в нужный вид... или преобразовывать в ручную...

Автор: dimaximo 29.4.2010, 09:42
Спасибо большое за некоторые просветы...вобщем, получилось только так:
Код

...
repeat
   for R:=1 to Y do
    begin
     DateTimeToString(s,'t',FloatToDateTime(StrToFloat(RangeMatrix[K+1,R])));
     SG1.Cells[(R),(K)]:=s;
    end; 
    SG1.RowCount:=K+1;
    inc(K,1);
 until K>X;
...
 

Автор: Albinos_x 29.4.2010, 13:59
Цитата(dimaximo @  29.4.2010,  09:42 Найти цитируемый пост)
FloatToDateTime(StrToFloat(RangeMatrix[K+1,R])));

транная конструкция, а что так не прокатило:
Код

TDateTime(RangeMatrix[K+1,R])


Автор: dimaximo 29.4.2010, 15:30
попробывал...выдает ошибку Statement expected, but expression of type 'TDateTime' found

Добавлено через 31 секунду
параметр что ли какой-то упущен

Автор: dimaximo 29.4.2010, 16:01
пробывал вставлять конструкцию...не идёт 
Код

var i:real;
      s:string;
...{в указанном диапазоне данные формата h:mm}
for r:=4 to Y do
     if (XLApp.Range['A4',EmptyParam].NumberFormat<>'h:mm;@') 
     then begin
               XLApp.Range['A4',XLApp.Cells.Item[r,k]].Value:='0'
               xlapp.Range['A4',XLApp.Cells.Item[r,k]].NumberFormat:='h:mm;@';
               i:=xlapp.Range['A4',XLApp.Cells.Item[r,k]].Text;                      {в отладчике i=0, а не 0.00}
               s:=xlapp.Range['A4',XLApp.Cells.Item[r,k]].NumberFormat      {в отладчике для всех ячеек s='основной', хотя большинство ячеек формата "Время"}
             end;
 
ни как не получается разобраться в этом  smile А хотелось бы сделать проверку - какие данные записаны в ячейке: с общим форматом или время... Те что с общим форматом - сделать 0:00. Может у вас будут какие-нибудь идеи smile 

Автор: Albinos_x 29.4.2010, 16:25
Цитата(dimaximo @  29.4.2010,  15:30 Найти цитируемый пост)
попробывал...выдает ошибку Statement expected, but expression of type 'TDateTime' found

хм... а если так:
Код

DateTimeToString(s,'t', Double(RangeMatrix[K+1,R]));


Добавлено через 1 минуту и 30 секунд
Цитата(dimaximo @  29.4.2010,  16:01 Найти цитируемый пост)
['A4',XLApp.Cells.Item[r,k]].

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

Добавлено через 9 минут и 37 секунд
Проверь, есть ли у XLApp.Cells.Item[r,k] свойство NumberFormat, если есть, то используй его, если нет, то для адресации по ячейкам (получения буквенного адреса) для XLApp.Range['A4','a3'] используй функцию, которую я приводил в теме http://forum.vingrad.ru/forum/topic-84634.html# :
Код

// организую адресацию по столбцам в Excel
function AddresColExcel(const Num:word):string;
var len, N:word;
ch:string;
begin
N:=Num;
ch:=char(ord('A')+(Num mod 26));
N:=N div 26;
while N<>0 do
begin
len:=Length(ch)+1;
SetLength(ch,Len);
ch[len]:=char(ord('A')+(N mod 26)-1);
N:=N div 26;
end;
len:=Length(ch);
SetLength(Result,len);
for n:=1 to len do
Result[n]:=ch[len+1-n];
end;


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)