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

 



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

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 22.12.2018, 22:25
Shkolnik_17 Shkolnik_17 вне форума
Прохожий
 
Регистрация: 18.12.2018
Сообщения: 4
Версия Delphi: Delphi7
Репутация: 10
По умолчанию Delphi 7 запись таблицы MO Excel в MO Access

Доброго времени суток. Пишу на Delphi 7 прогу для импорта Excel таблиц в базу данных Access. Лазил по форумам с надеждой найти какой нибудь аналог или общее описание, все без успехов. Delphi 7 изучаю не так давно, пару месяцев. Написал код, который загоняет таблицу Excel в массив. Смог вывести это в Memo, но как записать массив со значениями в базу данных Access не пойму. Подключаюсь к базе через компоненты ADO. Код что смог написать руководствуясь разными источниками прилагаю нижу. Сильно не ругайтесь, если неправильно задаю вопрос. Надеюсь на вашу помощь.
Код:
procedure TForm1.BitBtn1Click(Sender: TObject);
var
  i, j: Integer;
  S: string;
  Mass, MRange: Variant;
  ExcelApp, Book, Sheet: Variant;
 begin
   ExcelApp:= CreateOleObject('Excel.Application');
   ExcelApp.Visible:= True;
   Book:= ExcelApp.Workbooks.Open('D:\Documents and Settings\0\Рабочий стол\ImportExcelBD\Test1\Test1\Книга1.xls');
   Sheet:= Book.Sheets[1];
   MRange:= Sheet.Range[Sheet.Cells[2,1], Sheet.Cells[7, 3]];
   Mass:= MRange.Value;
   Memo1.Lines.Add('Прочитаный Массив ячеек:');
    for i:= VarArrayLowBound(Mass, 1) to VarArrayHighBound(Mass, 1) do
    begin
      S:= '';
       for j:= VarArrayLowBound(Mass, 2) to VarArrayHighBound(Mass, 2) do
         begin
           if j > 1 then
           S:= S + #9;
           S:= S + VarAsType(Mass[i, j], VarOleStr);
         end;
      Memo1.Lines.Add(S);   
    end;  
 end;
Test1.rar

Последний раз редактировалось Shkolnik_17, 22.12.2018 в 22:28.
Ответить с цитированием
  #2  
Старый 23.12.2018, 01:54
Аватар для lmikle
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 7,287
Версия Delphi: 7, XE3, 10.2
Репутация: 49087
По умолчанию

Ну если ты до данных ячейки добрался, то в чем проблема?
Код:
for i := VarArrayLowBound(Mass, 1) to VarArrayHighBound(Mass, 1) do
begin
  ADOTable1.Append;
  ADOTable1.Fields[0].AsString :=  VarAsType(Mass[i, VarArrayLowBound(Mass, 2)], VarOleStr);
  ADOTable1.Fields[0].AsString :=  VarAsType(Mass[i, VarArrayLowBound(Mass, 2)+1], VarOleStr);
  ADOTable1.Fields[0].AsString :=  VarAsType(Mass[i, VarArrayLowBound(Mass, 2)+2], VarOleStr);
  //... сколько у тебя там ячеек...
  ADOTable1.Post;
end;

А вообще можно попроще сделать.
Тут всавка в MemTable, но это не принципиально, с ADOTable будет работать точно так же.
Это собственно чтение из Экселя:
Код:
procedure XlsLoad(AFileName : String; ACallBack : TLoadCallBack);
var
  ExcelApp : OleVariant;
  WrkBook : OleVariant;

  I : Integer;

  ASheet : String;
  ARowFrom, ARowTo : Integer;
  RI : TRequirementInfo;
  RS : TRequirementSchema;
begin
  If @ACallBack = Nil Then Raise Exception.Create('Callback doesn''t set.');
  If Not FileExists(AFileName) Then Raise Exception.Create('File doesn''t exist.');

  ExcelApp := CreateOleObject('Excel.Application');
  Try
    WrkBook := ExcelApp.Workbooks.Open(AFileName);
    Try
      If Not GetSheet(ExcelApp,ASheet,RS) Then Exit;

      If Not GetRange(WrkBook, ASheet, ARowFrom, ARowTo)
        Then Raise Exception.Create('Can''t find cells range.');
      If (ARowTo - ARowFrom) < 1 Then Raise Exception.Create('Cells range is empty.');

      For I := ARowFrom To ARowTo Do
        Begin
          If GetRequirement(WrkBook,ASheet,I,RS,RI)
            Then ACallBack(RI);
        End;
    Finally
      WrkBook := NULL;
    End;
  Finally
    ExcelApp.Quit;
    ExcelApp := NULL;
  End;
end;

function GetRequirement(Book : OleVariant; Sheet : String; Row : Integer; Schema : TRequirementSchema; var RI : TRequirementInfo) : Boolean;
var
  Buf : String;
begin
  Result := False;
  Try
    RI.Number := StrToInt(Book.WorkSheets[Sheet].Range['A'+IntToStr(Row)].Text);
    RI.ReqName := Book.WorkSheets[Sheet].Range['B'+IntToStr(Row)].Text;

    RI.TgtName := Trim(Book.WorkSheets[Sheet].Range['C'+IntToStr(Row)].Text);
    Buf := Trim(Book.WorkSheets[Sheet].Range['D'+IntToStr(Row)].Text);
    ParseType(Buf,RI.TgtType,RI.TgtTypeLen,RI.TgtTypeLenDec);

    RI.SrcName := Trim(Book.WorkSheets[Sheet].Range['I'+IntToStr(Row)].Text);
    Buf := Trim(Book.WorkSheets[Sheet].Range['J'+IntToStr(Row)].Text);
    ParseType(Buf,RI.SrcType,RI.SrcTypeLen,RI.SrcTypeLenDec);

    Buf := Book.WorkSheets[Sheet].Range['K'+IntToStr(Row)].Text;
    Buf := Trim(UpperCase(Buf));
    RI.Nulls := (Buf = 'YES') Or (Buf = 'Y') Or (Buf = 'NULL');

    RI.Normalize := False;

    // Fix empty logical name
    If Trim(RI.ReqName) = '' Then RI.ReqName := RI.TgtName;

    Result := True;
  Except
  End;
end;
А вот функция, которая будет вызываться из вышеприведенной (соственно вставка):
Код:
procedure TMainForm.AddRow(RI: TRequirementInfo);
var
  Buf : String;
  bGo : Boolean;
begin
  mdReqs.Append;
  Try
    // Exclude lines with empty ('', n/a, derived) source field.
    Buf := AnsiUpperCase(Trim(RI.SrcName));
    bGo := Not((Buf = '') Or (Buf = 'N/A') Or (Buf = 'DERIVED'));

    mdReqs.FieldByName('Go').AsBoolean := bGo;
    mdReqs.FieldByName('Num').AsInteger := RI.Number;
    mdReqs.FieldByName('Name').AsString := RI.ReqName;
    mdReqs.FieldByName('TgtName').AsString := RI.TgtName;
    mdReqs.FieldByName('TgtType').AsString := RI.TgtType;
    mdReqs.FieldByName('TgtTypeLen').AsInteger := RI.TgtTypeLen;
    mdReqs.FieldByName('TgtTypeLenDec').AsInteger := RI.TgtTypeLenDec;
    mdReqs.FieldByName('SrcName').AsString := RI.SrcName;
    mdReqs.FieldByName('SrcType').AsString := RI.SrcType;
    mdReqs.FieldByName('SrcTypeLen').AsInteger := RI.SrcTypeLen;
    mdReqs.FieldByName('SrcTypeLenDec').AsInteger := RI.SrcTypeLenDec;
    mdReqs.FieldByName('Nulls').AsBoolean := RI.Nulls;
    mdReqs.FieldByName('Normalize').AsBoolean := RI.Normalize;
    mdReqs.FieldByName('ExtValues').AsString := '';
    mdReqs.Post
  Except
    mdReqs.Cancel;
  End;
end;
mdReqs - это наследник TTable (ну если по простому...)
Не смотри, что так сложно сделано, там не просто так все, нужно было еще кучу всего проверить и т.д.
Пойми принцип работы, тогда можно переписать короче и проще.

Последний раз редактировалось lmikle, 23.12.2018 в 02:04.
Ответить с цитированием
  #3  
Старый 23.12.2018, 11:05
Shkolnik_17 Shkolnik_17 вне форума
Прохожий
 
Регистрация: 18.12.2018
Сообщения: 4
Версия Delphi: Delphi7
Репутация: 10
По умолчанию

Цитата:
Сообщение от lmikle
Ну если ты до данных ячейки добрался, то в чем проблема?
Код:
for i := VarArrayLowBound(Mass, 1) to VarArrayHighBound(Mass, 1) do
begin
  ADOTable1.Append;
  ADOTable1.Fields[0].AsString :=  VarAsType(Mass[i, VarArrayLowBound(Mass, 2)], VarOleStr);
  ADOTable1.Fields[0].AsString :=  VarAsType(Mass[i, VarArrayLowBound(Mass, 2)+1], VarOleStr);
  ADOTable1.Fields[0].AsString :=  VarAsType(Mass[i, VarArrayLowBound(Mass, 2)+2], VarOleStr);
  //... сколько у тебя там ячеек...
  ADOTable1.Post;
end;
Тут все понятно, в таблицу вставляешь новую строку и присваиваешь каждой колонке значение из массива.
А если мне не известно количество колонок в Excel, как циклом загнать все значения массива в Access таблицу.
В общем хочу получить такой вариант: выбираю файл Excel и считываю все значения из области ячеек, и циклом загоняю их в Access.
По поводу второго твоего предложения я пока разбираюсь.
Ответить с цитированием
  #4  
Старый 23.12.2018, 11:23
Shkolnik_17 Shkolnik_17 вне форума
Прохожий
 
Регистрация: 18.12.2018
Сообщения: 4
Версия Delphi: Delphi7
Репутация: 10
По умолчанию

lmikle, Опишу полную картину. Есть некая система опроса счетчиков, она значения показаний выгружает в Excel. Нужно из этого файла Excel считать все значения и загнать в БД Access для хранения. Колонок в Excel всегда по разному, но максимум 30. Что можешь посоветовать? Если не смогу показать шефу результат в понедельник, хана мне.
Ответить с цитированием
  #5  
Старый 23.12.2018, 11:25
Аватар для lmikle
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 7,287
Версия Delphi: 7, XE3, 10.2
Репутация: 49087
По умолчанию

Дык, видимо, ты не понимаешь что такое таблица в Access.
Таблица - это заранее заданная структура данных. Т.е. ко-во колонок и их типы заранее определены.

В принципе, можно динамически создавать таблицы.
Коли ты знаешь кол-во колонок в Excel, то тогда можно сформировать что-то типа:
Код:
var
  N : Integer;
  I : Integer;
  S : String;
  Nm : String;
begin
  N := GetNumberOfColumns; // Получили кол-во колонок из Excel
  Nm := GetTableName; // Получили имя для таблицы
  S := 'CREATE TABLE ' + Nm + ' (';
  For I := 1 To N Do
    Begin
      S := S + 'Field_'+IntToStr(I)+' VARCHAR(255)';
      If I < N Then S := S + ',';
    End;
  S := S + ')';
  ADOQuery.SQL.Text := S;
  ADOQuery.ExecSQL;
Такой код создаст таблицу с нужным кол-вом колонок, куда уже и вставлять данные.
Ответить с цитированием
  #6  
Старый 23.12.2018, 11:59
Shkolnik_17 Shkolnik_17 вне форума
Прохожий
 
Регистрация: 18.12.2018
Сообщения: 4
Версия Delphi: Delphi7
Репутация: 10
По умолчанию

lmikle, Вот такая ошибка.
2018-12-23_11-53-37.png
Код написал по твоему примеру.
Код:
procedure TForm1.BitBtn3Click(Sender: TObject);
var
  NCol, I: Integer;
  NameTab, S: string;
begin
  ADOConnection1.ConnectionString:= 'Provider=Microsoft.Jet.OLEDB.4.0;Data Source=DB1.mdb;Persist Security Info=False';
  ADOConnection1.Connected:= True;
  ADOQuery1.Connection:= ADOConnection1;
  NCol:= 10; //количество колонок
  NameTab:= 'Tabl1'; // название таблицы
  S:= 'CREATE TABLE'+NameTab+'(';
  for I:= 1 to NCol do
    begin
      S:= S+'Field_' +IntToStr(I)+'VARCHAR(200)';
      if I < NCol then S:= S+ ',';
    end;
  S:= S+')';
  ADOQuery1.SQL.Text:= S;
  ADOQuery1.ExecSQL;  
end;
В чем мой косяк?
Ответить с цитированием
  #7  
Старый 24.12.2018, 06:54
Аватар для lmikle
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 7,287
Версия Delphi: 7, XE3, 10.2
Репутация: 49087
По умолчанию

В том, что пробелы в строках удалять было не надо.
Выведи получившуюся команду и посмотри. у тебя слились:
- ключевое слово TABLE и имя таблицы
- имена колонок и их тип данных
- ну и скобочки, хотя это не важно
Ответить с цитированием
Ответ



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

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

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

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


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


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources", 2004-2019

ВКонтакте   Facebook   Twitter