Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Круглый стол
  
Правила КС
>> Настройки

Фильтр вопросов
>> Новые вопросы
отслеживать по
>> Новые ответы

Избранное

Страница вопросов
Поиск по КС


Специальные проекты:
>> К л ю к в а
>> Г о л о в о л о м к и

Вопрос №

Задать вопрос
Off-topic вопросы

Помощь

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  01:46[Войти] | [Зарегистрироваться]
Ответ на вопрос № 45934

Вопросы с аналогичными сообщениями об ошибках:
  • Invalid variant type conversion (27)

    17-10-2006 07:51
    Здравствуйте. Необходимо вытянуть данные из MS Sql Server в Excel.
    Использую набор компонентов SDac. У Query свойство FetchAll->false и FetchRows=50.
    То есть засасывать по 50 записей. Это все делается для ускорения, так как 5000 записей сразу будут закачиваться долго, да и не всем они сразу нужны, и уменьшения трафика в сети.
    В связи с этим, при экспорте в Excel создать вариантный массив с полученными данными не представляется возможным, так как при создании вариантного массива ему четко нужно указать размерность. Проблема в том, что у SDac'овского Query свойство TMSQuery.RecordCount меняется, как только доходим до 50-ой записи и становится 100. И так до последней.
    Поэтому, делаю многомерный динамический массив и постепенно, с помощью SetLength его наращиваю.
    Возникает необходимость, перед экспортом этого динамического массива перевести его в вариантный.
    В Help'е к Delphi нашел процедуру DynArrayToVariant, которая и должна делать подобное.
    Прототип: DynArrayToVariant(var V: Variant; const DynArray: Pointer; TypeInfo: Pointer).
    Я его вызываю так: DynArrayToVariant(ArrayA; ArrayB; TypeInfo(variant)).
    Но так не работает. Выдает: 'Invalid variant type conversion'.
    Как мне перевести динамический массив в вариантный используя эту процедуру или сделать это как-нибудь иначе?

    [+] Добавить в избранные вопросы

    Отслеживать ответы на этот вопрос по RSS

    Ответы:


    Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице.
    Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.

    14-02-2007 13:12
    У Query свойство FetchAll->false и FetchRows=50.
    Если такие ограничения у Query, то стоит ли всё загонять в динамический массив, может, лучше и в Excel перегонять по 50, 100 или 150 и т.д. строк

    14-02-2007 12:56
    В трассировке DynArrayToVariant видно, что TypeInfo нужно передовать для динамического массива, а не его элементов. Все ArrayB[i] должны быть одинаковой длины. В таком варианте процедура работает.

    type
      TDynArrDynArrString = array of array of string;
    var
      ArrayB : TDynArrDynArrString;
    ...
    // заполнение дин. массива
    ...
    //DynArrayToVariant(ArrayA, ArrayB, TypeInfo(string));

    DynArrayToVariant(ArrayA, ArrayB, TypeInfo(TDynArrDynArrString));
    WorkBook.WorkSheets[1].Range[Cell1, Cell2].Value:=ArrayA;



    18-10-2006 03:28 | Сообщение от автора вопроса
    Господа, есть какая-то залипуха, не позволяющая перевести динамический массив в вариант. Работает только тупой цикл, с поэлементным присвоением. Тем не менее, на ум пришел другой вариант: последовательно формировать в цикле вариантные массивы, длиной в то количество записей, сколько за раз засасывает SDac'овский Query и передавать серверу Excel'а. Получается, что-то типа поячеичного присвоения (помассивное). В итоге, обработчик выглядит так:

    procedure TForm1.Button2Click(Sender: TObject);
    var
      Cell1, Cell2 , ArrayA : Variant;
      nBeginCol, nBeginRow, nRow, i, j : integer;
      nRowCount, nColCount : integer;
    begin
      MSQuery1.Close; MSQuery1.Open;
      MSQuery1.First;

      ExcelApp:=null; WorkBook:=null;

      nBeginCol:=1; nBeginRow:=4; // Положение первой ячейки для вывода данных

      nColCount:=MSQuery1.Fields.Count; // Число столбцов фиксированное

      ExcelApp := CreateOleObject('Excel.Application');
      ExcelApp.Application.EnableEvents := false;
      Workbook := ExcelApp.WorkBooks.Add;

      ExcelApp.Cells.Item[2,1] :='Экспорт данных';

      while nRowCount<MSQuery1.RecordCount do
        begin
          nRowCount:=MSQuery1.RecordCount+1;
          ArrayA:=VarArrayCreate([1, nRowCount, 1, nColCount], varVariant);
          MSQuery1.Locate('Kod_Id',MSQuery1Kod_Id.Value,[]); // Продолжаем с места, где остановились

          for i:=nBeginRow-3 to nRowCount do
            begin
              for j:=1 to MSQuery1.Fields.Count do
                ArrayA[i,j]:=Trim(MSQuery1.Fields.Fields[j-1].AsString);

              MSQuery1.Next;
            end;

          // Считаем координаты области, куда наш массив будем кидать
          Cell1 := WorkBook.WorkSheets[1].Cells[nBeginRow, nBeginCol];
          Cell2 := WorkBook.WorkSheets[1].Cells[nBeginRow  + nRowCount - 2, nBeginCol + nColCount-1];

          WorkBook.WorkSheets[1].Range[Cell1, Cell2]:=ArrayA;
          WorkBook.WorkSheets[1].Range[Cell1, Cell2].NumberFormat:='@';
          ExcelApp.Cells.Range[Cell1, Cell2].Columns.AutoFit;

          nBeginRow:=nBeginRow+nRowCount;

          ArrayA:=null; // Удаляем наш массив
        end;

      ExcelApp.Visible := true;
    end;

    17-10-2006 23:22
    Ошибка, конвертации может возникать на мой взгляд либо из-за слишком большого объёма данных, либо из-за самих данных...

    Попробуйте, сконвертировать в Variant, каждую строку динамического массива в отдельности, быть может найдёте ту на которой конвертация стопориться...

    что- то типа
    try

    for i:=0 to high(ArrayB) do
        ArrayA := Variant(ArrayB[i])
    except
        MessageBox(0, PChar(inttostr(i),'',0));
    end;

     
    P.S. Может быть строки в массиве имеют разную длину?


    17-10-2006 21:41 | Сообщение от автора вопроса
    Нет господа, SDac - потому, что SDac. Всю прогу переделывать на ADO не собираюсь. В перспективе 10000 записей и более. Мулька с Variant(arr) не работает. Проблема в самой конвертации из динамического массива в вариант. Вот код:
    var
      ArrayB : array of array of string;
    ...
    // заполнение дин. массива
      while not quTempExcel.Eof do
        begin
          if Length(ArrayB)<(quTempExcel.RecordCount+1) then
            begin
              SetLength(ArrayB, quTempExcel.RecordCount+1);
              nRowCount:=quTempExcel.RecordCount+1;
            end;

          SetLength(ArrayB[nRow], nColCount);

          for i:=0 to nColCount-1 do
            ArrayB[nRow, i]:=Trim(quTempExcel.FieldByName(slFieldName[i]).AsString);

          Inc(nRow);
          quTempExcel.Next;
        end;
    ...
    WorkBook.WorkSheets[1].Range[Cell1, Cell2].Value:=Variant(ArrayB); //Не работает
    Конец кода.

    Такое тоже не работает:
    DynArrayToVariant(ArrayA, ArrayB, TypeInfo(string));
    WorkBook.WorkSheets[1].Range[Cell1, Cell2].Value:=ArrayA;

    Пробовал делать следующее:
    ArrayA := VarArrayCreate([1, nRowCount, 1, nColCount], varVariant);

      for i:=1 to nRowCount-1 do
        for j:=1 to nColcount do
          ArrayA[i,j]:=ArrayB[i-1,j-1];

    Такой перегон работает, но 10000 записей прогонять 2-ы - глупо и не рационально...

    17-10-2006 10:46
    Если просто вытянуть используй DTS IMPORT\EXPORT WIZARD - SQL Server

    17-10-2006 08:47
    А что мешает сделать это с помощью ADO? Код достаточно прост. Около 3000 записей выводятся секунд за 10-15. И проблем особых нет. Даже не требуется установленного Excel'а.

    17-10-2006 08:36

      arr : array of string;
    begin
    ...
        setLength(arr,2);
        arr[0] := '1';
        arr[1] := '2';
    ...
        Sheet.Range['C20:D21'].Value := Variant(arr);


    17-10-2006 08:21
    Гляньте здесь
    http://msdn2.microsoft.com/en-us/library/ms365294.aspx

    Добавьте свое cообщение

    Вашe имя:  [Войти]
    Ваш адрес (e-mail):На Королевстве все адреса защищаются от спам-роботов
    контрольный вопрос:
    Какой месяц идет после марта?
    в качестве ответа на вопрос или загадку следует давать только одно слово в именительном падеже и именно в такой форме, как оно используется в оригинале.
    Надоело отвечать на странные вопросы? Зарегистрируйтесь на сайте.
    Тип сообщения:
    Текст:
    Жирный шрифт  Наклонный шрифт  Подчеркнутый шрифт  Выравнивание по центру  Список  Заголовок  Разделительная линия  Код  Маленький шрифт  Крупный шрифт  Цитирование блока текста  Строчное цитирование
  • вопрос Круглого стола № XXX

  • вопрос № YYY в тесте № XXX Рыцарской Квинтаны

  • сообщение № YYY в теме № XXX Базарной площади
  • обсуждение темы № YYY Базарной площади
  •  
     Правила оформления сообщений на Королевстве

    Вопросы с аналогичными сообщениями об ошибках:
  • Invalid variant type conversion (27)


    Страница избранных вопросов Круглого стола.
  •   
    Время на сайте: GMT минус 5 часов

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

    Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
    Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

     
    © При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
    Все используемые на сайте торговые марки являются собственностью их производителей.

    Яндекс цитирования