Форум программистов, компьютерный форум, киберфорум
Наши страницы
Delphi для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 5.00/6: Рейтинг темы: голосов - 6, средняя оценка - 5.00
Outwork
4 / 4 / 3
Регистрация: 05.08.2014
Сообщений: 54
1

Как скопировать содержимое листа Excel в переменную типа Variant

03.12.2014, 02:57. Просмотров 1128. Ответов 7
Метки нет (Все метки)

Доброго времени суток! Передо мной встал следующий вопрос: есть книга Excel с листом данных, c листа надо считать диапазон данных в переменную типа Variant (однако возможны и другие варианты, просто в нынешней реализации это именно Variant) и благополучно завершить работу с Excel. Сейчас это выглядит так:
1. Сначала функция считывания диапазона (предварительно книга естественно открывается, причем только для чтения)
Переменные:
Delphi
1
2
ExlApp, Sheet: OLEVariant;
FData:Variant;
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function RangeRead:boolean;
var Rows, i: integer;
begin
  //определяем количество строк и столбцов таблицы
  Rows:=sheet.Range[Char(96 + 6) + IntToStr(65536)].end[3].Rows.Row;
  if rows = 1 then
  begin
  ShowMessage('База данных не содержит записей!');
  for i := 1 to RiskForm.StringGrid1.RowCount - 1
  do RiskForm.StringGrid1.Rows[i].Clear; //Очистка
  result := false;
  end else
  begin
  //считываем данные всего диапазона
      FData :=Sheet.Range[sheet.cells[2,1],sheet.cells[rows,24]];
      result := true;
  end;
end;
2. Затем функция прекращения работы привязанного Excel
Delphi
1
2
3
4
5
6
7
8
9
10
11
function StopExcel:boolean;
begin
  try
    if exlapp.Visible then exlapp.Visible:=false;
    exlapp.Quit;
    exlapp:=Unassigned;
    Result:=True;
  except
    Result:=false;
  end;
end;
Далее хочу получить в переменной FData считанный диапазон, знаю правда, что переменная содержит только указатель на объект Excel.Application и при его уничтожении переменная FData остается пустым!

Какие есть способы реализовать задуманное? Буду признателен за любой совет! Заранее спасибо!
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
03.12.2014, 02:57
Ответы с готовыми решениями:

Как вывести переменную Variant(Excel) в компонент OleContainer ?
Всем привет! У меня получается работать с Excel документом через переменную Variant, и у меня...

Как записать в массив типа variant значение типа double?
Есть массив массивов типа variant. В первой ячейке (элементе) текст, в остальных 4 нули. Текст-1...

Как скопировать участок памяти в переменную типа Variant?
Стоит ли игра свеч? Private Declare Sub memcpy Lib "kernel32.dll" Alias "RtlMoveMemory" (lpvDest...

Как скопировать данные из одного листа Excel на другой в Java?
Как скопировать данные из одного листа Excel на другой в Java?

Библиотека gmp. Как записать содержимое файла в переменную типа mpz_t?
Всем привет. Подскажите, пожалуйста, почему в переменную P ничего не записывается?Результат равен...

7
Vabos
120 / 120 / 28
Регистрация: 12.12.2011
Сообщений: 425
03.12.2014, 13:36 2
Знаю, что можно создать вариантный массив, заполнить его и разом запихнуть в диапазон:
Delphi
1
2
3
4
5
6
7
var A:Variant;
begin
   A:=VarArrayCreate([1,n,1,m],VarVariant);
   //заполняем...
   Rng.Value:=AA; //ExcelRange
   AA:=Unassigned;
end;
В обратную сторону тож должно работать.
0
Outwork
4 / 4 / 3
Регистрация: 05.08.2014
Сообщений: 54
04.12.2014, 19:00  [ТС] 3
Цитата Сообщение от Vabos Посмотреть сообщение
В обратную сторону тож должно работать.
Не совсем понял реализацию метода! Если не сложно то поподробнее немного! Что потом делать с этим вариантным массивом?
0
Vabos
120 / 120 / 28
Регистрация: 12.12.2011
Сообщений: 425
05.12.2014, 13:57 4
Так же готовим вариантный массив нужного размера. Затем выделяем на листе диапазон (ExcelRange) такого же размера и AA:=Rng.Value; Затем разбираем этот массив определяя тип каждого эл-та и пихаем в свои структуры.
0
05.12.2014, 13:57
Mawrat
12856 / 5759 / 1701
Регистрация: 19.09.2009
Сообщений: 8,807
08.12.2014, 02:13 5
Цитата Сообщение от Outwork Посмотреть сообщение
Далее хочу получить в переменной FData считанный диапазон, знаю правда, что переменная содержит только указатель на объект Excel.Application и при его уничтожении переменная FData остается пустым!
Чтобы прочитать сами данные диапазона, а не ссылку на объект диапазона, надо обратиться к свойству Excel.Range.Value.
Т. е., надо заменить:
Delphi
1
FData := Sheet.Range[sheet.cells[2,1],sheet.cells[rows,24]];
на:
Delphi
1
FData := Sheet.Range[sheet.cells[2,1],sheet.cells[rows,24]].Value;
При этом, если диапазон Excel состоит из нескольких ячеек, то FData будет содержать вариантный массив с данными этих ячеек. Если диапазон Excel представлен одной ячейкой, то FData будет являться отдельной переменной типа Variant с данными этой ячейки.
1
serg55
2 / 2 / 1
Регистрация: 15.08.2014
Сообщений: 170
26.02.2015, 11:36 6
Цитата Сообщение от Mawrat Посмотреть сообщение
1
FData := Sheet.Range[sheet.cells[2,1],sheet.cells[rows,24]].Value;
Mawrat, вот я тут задумался: объявлять размер вариантного массива с помощью VarArrayCreate(m,n,m1,n1,MyMass) не нужно получается ?
То есть достаточно объявить MyMass : Variant и можно в него сразу пихать диапазон ячеек, а размер массива получиться автоматически ? Подскажи ? А то на разных форумах по разному делают, кто-то вычислив количество строк и столбцов в файле экселя, определяет по этим данным размер вариантного массива, а кто-то нет. Как лучше сделать ? Спасибо !
0
Mawrat
12856 / 5759 / 1701
Регистрация: 19.09.2009
Сообщений: 8,807
26.02.2015, 12:36 7
Цитата Сообщение от serg55 Посмотреть сообщение
Mawrat, вот я тут задумался: объявлять размер вариантного массива с помощью VarArrayCreate(m,n,m1,n1,MyMass) не нужно получается ?
То есть достаточно объявить MyMass : Variant и можно в него сразу пихать диапазон ячеек, а размер массива получиться автоматически ? Подскажи ?
Да - достаточно в переменную типа Variant записать значение свойства Excel.Range.Value. При этом есть следующие особенности:
- Если диапазон содержит больше одной ячейки, то в переменную будет записан двумерный вариантный массив, в котором индексация элементов по обоим измерениям начинается с единицы.
- Если диапазон содержит только одну ячейку, то в переменную будет записано значение, не являющееся вариантным массивом.
Пример функции, которая читает данные из заданного диапазона Excel и возвращает их в виде двумерного вариантного массива:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
uses
  ComObj;
 
{Функция читает данные с листа MS Excel и возвращает их в виде вариантного массива.
Для получения данных надо задать параметры:
- aExSh - ссылка на интерфейс листа MS Excel.
- aRow1, aCol1, aRow2, aCol2 - координаты диапазона из которого надо получить данные.
- Если aRow1 = 0, то в качестве значения будет использован номер самой верхней
  строки используемого диапазона (UsedRange.Row)
- Если Row2 = 0, то в качестве значения будет использован номер самой
  нижней строки в используемом диапазоне (UsedRange.Row + UsedRange.Rows.Count - 1).
- Если aCol1 = 0, то в качестве значения будет использован номер самого
  крайнего слева столбца в используемом диапазоне (UsedRange.Column).
- Если aCol2 = 0, то в качестве значения будет использован номер самого
  крайнего справа столбца в используемом диапазоне (UsedRange.Column + UsedRange.Columns.Count - 1).
 
Некоторые примеры вызова.
1. Получить с листа exSh данные диапазона "D2:F15" (="R2C4:R15C6"):
  VArr := ExRangeToVArr(exSh, 2, 4, 15, 6);
2. Получить с листа exSh данные из столбца "D", начиная с ячейки "D2" (="R2C4"):
  VArr := ExRangeToVArr(exSh, 2, 4, 0, 4);
3. Получить с листа exSh данные из столбцов D, E, F, начиная с ячейки "D2" (="R2C4"):
  VArr := ExRangeToVArr(exSh, 2, 4, 0, 6);
4. Получить с листа exSh данные из второй строки, начиная с ячейки "D2" (="R2C4:R2C"):
  VArr := ExRangeToVArr(exSh, 2, 4, 2, 0);
5. Получить с листа exSh все имеющиеся данные, начиная с ячейки "D2" (="R2C4"):
  VArr := ExRangeToVArr(exSh, 2, 4, 0, 0);
6. Получить с листа exSh все данные используемого диапазона:
  VArr := ExRangeToVArr(exSh, 0, 0, 0, 0);
7. Получить с листа exSh все имеющиеся данные, начиная от верхнего левого угла листа:
  VArr := ExRangeToVArr(exSh, 1, 1, 0, 0);  }
function ExRangeToVArr(const aExSh : OleVariant; const aRow1, aCol1, aRow2, aCol2 : Integer) : Variant;
var
  exCell1, exCell2 : OleVariant;
  V : Variant;
  Row1, Col1, Row2, Col2 : Integer;
begin
  VarClear(Result);
  //Номер верхней строки.
  if aRow1 <> 0 then
    Row1 := aRow1
  else
    Row2 := aExSh.UsedRange.Row;
  //Номер крайнего левого столбца.
  if aCol1 <> 0 then
    Col1 := aCol1
  else
    Col1 := aExSh.UsedRange.Column;
  //Номер нижней строки.
  if aRow2 <> 0 then
    Row2 := aRow2
  else
    Row2 := aExSh.UsedRange.Row + aExSh.UsedRange.Rows.Count - 1;
  //Номер крайнего правого столбца.
  if aCol2 <> 0 then
    Col2 := aCol2
  else
    Col2 := aExSh.UsedRange.Column + aExSh.UsedRange.Columns.Count - 1;
  //Если ячейка exCell2 расположена выше либо левее, чем exCell1, то это означает, что данных нет.
  if (Row2 < Row1) or (Col2 < Col1) then
    Exit;
  exCell1 := aExSh.Cells[Row1, Col1]; //Левая верхняя ячейка диапазона.
  exCell2 := aExSh.Cells[Row2, Col2]; //Правая нижняя ячейка диапазона.
 
  //Читаем данные диапазона в переменную V.
  V := aExSh.Range[exCell1, exCell2].Value;
  {Если диапазон состоит из нескольких ячеек, то V является вариантным массивом.
  Если диапазон состоит из одной ячейки, то V не является массивом и представляет
  данные одной ячейки. В этом случае массив надо создать вручную.}
  if VarIsArray(V) then //Если V является массивом.
    Result := V
  else //Если V не является массивом, то создаём двумерный массив, содержащий только один элемент.
  begin
    Result := VarArrayCreate([1, 1, 1, 1], varVariant);
    Result[1, 1] := V;
  end;
end;
Отдельные значения, прочитанные из ячеек Excel, могут содержать данные разных типов. Это можно учитывать следующим образом:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
procedure TForm1.Button1Click(Sender : TObject);
var
  exApp, exBook, exSh : OleVariant;
  VArr, V : Variant;
  S : String;
  i, j : Integer;
  Od : TOpenDialog;
begin
  //Диалог выбора файла.
  Od := OpenDialog1; //OpenDialog1 уже должен быть на форме.
  if Od.InitialDir = '' then //Начальная папка - та, где расоложен исполняемый файл программы.
    Od.InitialDir := ExtractFilePath(ParamStr(0));
  if not Od.Execute then //Диалог выбора файла.
    Exit;
  if not FileExists(Od.FileName) then //Проверка существования файла.
  begin
    MessageBox(Handle, 'Файл с заданным именем не найден! Действие отменено.',
      'Внимание!', MB_OK + MB_ICONWARNING + MB_APPLMODAL);
    Exit;
  end;
 
  //Запуск экземпляра Excel и получение ссылки на корневой объект (Excel.Application).
  exApp := CreateOleObject('Excel.Application');
  //Делаем видимым окно MS Excel. На время отладки или на постоянной основе.
  exApp.Visible := True;
  //Открываем раб. книгу и получаем ссылку на неё.
  exBook := exApp.Workbooks.Open(FileName:=Od.FileName);
  //Получаем ссылку на первый лист рабочей книги.
  exSh := exBook.Worksheets[i];
    
  //Получаем с листа MS Excel все данные из колонок B, C, D, E (это колонки 2..5),
  //начиная со строки 4 и ниже до конца используемого диапазона (UsedRange).
  VArr := ExRangeToVArr(exSh, 4, 2, 0, 5);
 
  //Распечатка полученных данных в Memo.
  Memo1.Text := 'Полученные данные:';
  for i := 1 to VarArrayHighBound(aVArr, 1) do
  begin
    S := '';
    for j := 1 to VarArrayHighBound(aVArr, 2) do
    begin
      if j > 1 then
        S := S + #9;
      V := VArr[i, j];
      case VarType(V) of //Преобразование в зависимости от типа данных.
        varOleStr : S := S + V; //Строковые данные.
        varDouble : S := S + FloatToStr(V); //Числовые данные.
        varDate   : S := S + FormatDateTime('dd.mm.yyyy"-"hh.nn.ss', V); //Данные типа даты и времени.
        varEmpty  : S := S + ''''''; //Пустое значение (из пустой ячейки).
        else
          S := S + '<?>'; //Данные незарегистрированного типа.
      end;
    end;
    Memo1.Lines.Add(S);
  end;
 
  //exBook.Close; //Закрываем рабочую книгу.
  //exApp.Quit;   //Закрываем MS Excel.
end;
1
serg55
2 / 2 / 1
Регистрация: 15.08.2014
Сообщений: 170
26.02.2015, 13:30 8
Огромное спасибо !
0
26.02.2015, 13:30
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
26.02.2015, 13:30

Как задать соответствие одних значений, одного листа Excel, значениям другого листа Excel
Есть лист Excel ,значения в нем постоянны и находятся на одном месте (в одном столбце и в одной...

Скопировать строку из одного листа в другой (Excel)
Не понимаю почему работат. Worksheets('Work').Range(Cells(2, 1), Cells(2, 14)).Copy...

Нужно скопировать данные с закрытого листа Excel в открытый
Тут, уже несколдько вариантов постирал... Не могу правильно сформулировать вопрос... Вообщето...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru