Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2004.08.22;
Скачать: [xml.tar.bz2];

Вниз

Копирование данных через буфер из Excel в DBGrid...   Найти похожие ветки 

 
BoxTer   (2004-08-03 13:41) [0]

Вот возникла интересная ситуевина - требуется выполнить сабж: есть в экселе табличка, например - 3 столбца, 5 строчек. Скопировав ее Ctrl+C в буфер необходимо вставить эти данные в приложении в сетку DBGrid1 с таким же количеством строк и столбцов...

Заранее благодарен.


 
Sancho ©   (2004-08-03 13:50) [1]

Вообще ячейки (в буфере обмена) будут разделяться символом #9, а строки #13#10 (но это не точно т.к. копался я в этом давным-давно). Но это абсолютно не правильно, косяков не оберешься, то строчка выпадет, то ячейки объединятся особенно если ячеек много. Надо использовать OLE.


 
Digitman ©   (2004-08-03 13:53) [2]


> в сетку DBGrid1 с таким же количеством строк и столбцов


если DBGrid1 связан с НД, не допускающим редактирование данных/метаданных, то затея эта крива изначально


 
KSergey ©   (2004-08-03 14:08) [3]

> [2] Digitman ©   (03.08.04 13:53)

Я не пойму при чем тут все это говорить? В любом случае нет такой функциональности в стандартных компонентах. (или я ошибаюсь?)
Есть такая фигня. но это целая надстройка над DBGridEh.

Хотя сейчас глянул  наверное можно его отдельно выдрать при желании... Но жаба давит :)


 
KSergey ©   (2004-08-03 14:11) [4]

Все сделано как реакция на WM_PASTE грида. Откуда оно возьмется - решать вам. Или к другому месту это все прикрутить.

Ну за одно может у кого будет конструктивная (да хоть и не очень) критика. Часть внутренних ф-ций использовалась для тестов, но проверять мне лень.

В один пост наверняка не влезет, разобью.

{******************************************************************************
* Вставка строк из клипборда
* Вставляет начиная с текущего столбца
* Вставляет при след. условиях:
*  -грид в режиме вставки
*  -GataSet и Grid допускают редактирование
******************************************************************************}

procedure TdoDBGrid.WMPaste(var Msg: TMessage);
var
 i: Integer;
 StrLst: TStringList;
 SavCursor: TCursor;

 // из модуля ClipView RXLib
 // использовалась для тестов
 function ClipboardFormatName(Format: Word): string;
 var
   Buffer: array[0..255] of Char;
 begin
   SetString(Result, Buffer, GetClipboardFormatName(Format, Buffer, 255));
   if Result = "" then
     case Format of
       CF_BITMAP: Result := "CF_BITMAP";
       CF_DIB: Result := "CF_DIB";
       CF_DIF: Result := "CF_DIF";
       CF_METAFILEPICT: Result := "CF_METAFILEPICT";
       CF_ENHMETAFILE: Result := "CF_ENHMETAFILE";
       CF_OEMTEXT: Result := "CF_OEMTEXT";
       CF_PALETTE: Result := "CF_PALETTE";
       CF_PENDATA: Result := "CF_PENDATA";
       CF_RIFF: Result := "CF_RIFF";
       CF_SYLK: Result := "CF_SYLK";
       CF_TEXT: Result := "CF_TEXT";
       CF_TIFF: Result := "CF_TIFF";
       CF_WAVE: Result := "CF_WAVE";
       CF_UNICODETEXT: Result := "CF_UNICODETEXT";
       CF_HDROP: Result := "CF_HDROP";
       CF_LOCALE: Result := "CF_LOCALE";
       CF_MAX: Result := "CF_MAX";
       CF_OWNERDISPLAY: Result := "CF_OWNERDISPLAY";
       CF_DSPTEXT: Result := "CF_OWNERDISPLAY";
       CF_DSPBITMAP: Result := "CF_OWNERDISPLAY";
       CF_DSPMETAFILEPICT: Result := "CF_OWNERDISPLAY";
       CF_DSPENHMETAFILE: Result := "CF_OWNERDISPLAY";
       CF_PRIVATEFIRST: Result := "CF_OWNERDISPLAY";
       CF_PRIVATELAST: Result := "CF_OWNERDISPLAY";
       CF_GDIOBJFIRST: Result := "CF_OWNERDISPLAY";
       CF_GDIOBJLAST: Result := "CF_OWNERDISPLAY";
     end;
 end;

 // просто список форматов данных в буфере обмена
 // использовалась для тестов
 function TextClipboardFornats: String;
 const
   YN: array [Boolean] of String = ("No", "Yes");
 var
   FormatNum, i: Integer;
 begin
   Result := "";
   for i := 0 to Clipboard.FormatCount-1 do
   begin
     FormatNum := Clipboard.Formats[i];
     Result := Result
       + IntToStr (FormatNum)
       + " (" + ClipboardFormatName(FormatNum) + ") - "
       + YN[Clipboard.HasFormat(FormatNum)] + {#13} " | ";
   end;
 end;


 
KSergey ©   (2004-08-03 14:12) [5]

 // проверка строки на пустоту
 function IsEmptyStr (const AStr: String): Boolean;
 begin
   Result := Length(AStr) < 1;
 end;

 // присваивает указанное значение полю указанного столбца
 // работа через строковые значения, т.к. из клипборда вынимается текстовая информация
 procedure PasteCol (const nCol: Integer; const AStr: String);
 begin
   if NOT IsEmptyStr(AStr) then
     Columns[nCol].Field.AsString := AStr;
 end;

 // собственно добавление строки в грид
 // AStr - строка для вставки, содержащая колонки, разделенные табуляцией
 procedure PasteRow (AStr: String);
 var
   nPT: Integer;  // позиция табуляции
   nCol: Integer; // колонка для вставки
   isAllow: Boolean;  // флажек для пользователя "разрешить вставку"
 begin
   if DataLink.DataSet.State <> dsInsert then  DataLink.DataSet.Append;  // для последующих строк за первой
   try
     // предоставить пользователю возможность прописать значения в какие-либо поля при вставке строки
     isAllow := TRUE;
     if Assigned(OnRowPaste) then  OnRowPaste(Self, isAllow);
     if isAllow then
     begin
       // теперь разбить на составляющие и вставить поколоночно
       nCol := Col;
       if dgIndicator in Options then  Dec(nCol);
       while NOT IsEmptyStr(AStr) do
       begin
         nPT := Pos (#9, AStr);
         if nPT < 1 then  nPT := Length(AStr)+1;
         PasteCol (nCol, Copy(AStr, 1, nPT-1));
         Inc(nCol);
         if nCol >= Columns.Count then  Break;  // в буфере обмена было больше полей, чем осталось в гриде от текущего столбца - выход
         AStr := Copy (AStr, nPT+1, Length(AStr)-nPT);  // выделить остаток строки
       end;
       DataLink.DataSet.Post;
     end
     else
       DataLink.DataSet.Cancel;  // пользователь не разрешил вставку
   except
     DataLink.DataSet.Cancel;  // при ошибках - обязательно отменить изменения
     raise;
   end;
 end;


 
GanibalLector ©   (2004-08-03 14:12) [6]

на realcoding.net поищи.Там такой вопрос подымался и весьма успешно разрешился!!!


 
KSergey ©   (2004-08-03 14:13) [7]

begin   // TdoDBGrid.WMPaste
{ TODO -cГрид: попробовать сделать так, чтобы при режиме "не редактирование" вставлялось значение текста из буфера в ячейку (с предварительным переводом в состояние редактирования); возможно, придется проверить формат данных, хотя, наверняка, если не вставка (т.е. не режим для вставки строк) - пихать все в текущую ячейку }
 if ReadOnly OR NOT Assigned(DataLink.DataSet) OR NOT DataLink.DataSet.Active OR NOT DataLink.DataSet.CanModify OR (DataLink.DataSet.State <> dsInsert) OR NOT (dgdAllowRowPaste in FOptionsDO) then
   Exit;  // если по каким-то условиям нельзя произвести вставку - немедленный выход
 // итак, DataSet есть, открыт и в режиме вставки (на новой строке), ставка в грид строк - разрешена
 StrLst := TStringList.Create;
 try
   StrLst.Text := Clipboard.AsText;
   if StrLst.Count > 0 then  // буфер не пуст
   begin
     SavCursor := Screen.Cursor;
     Screen.Cursor := crHourGlass;
     DataLink.DataSet.DisableControls;
     try
       for i := 0 to StrLst.Count-1 do
         if NOT IsEmptyStr(StrLst[i]) then  PasteRow (StrLst[i]);
     finally
       DataLink.DataSet.EnableControls;
       Screen.Cursor := SavCursor;
     end;
   end;
 finally
   StrLst.Free;
 end;
end;


 
KSergey ©   (2004-08-03 14:15) [8]

Работает код из [4][5][7] KSergey © так: надо перейти на новую строку в гриде (режим вставки), встать на столбец, начиная с которого будем вставлять - ну и вызвать эту ф-цию.
Возможно, условия для кого-то не приемлемы, ну подшаманить.


 
KSergey ©   (2004-08-03 14:17) [9]

Да, там еще обработчик сделан OnRowPaste
Ну это можно смело убрать.


 
BoxTer   (2004-08-04 07:45) [10]

2KSergey.
Бааальшое сенкс. Все заработало, придется маненько доделать для моей задачи - а так усе отлично!


 
KSergey ©   (2004-08-04 08:14) [11]

> GanibalLector ©   (03.08.04 14:12)
> на realcoding.net поищи.

Там поиска нет, или я не нашел?


 
Digitman ©   (2004-08-04 09:25) [12]


> KSergey ©   (03.08.04 14:08) [3]
> > [2] Digitman ©   (03.08.04 13:53)
>
> Я не пойму при чем тут все это говорить? В любом случае
> нет такой функциональности в стандартных компонентах. (или
> я ошибаюсь?)


я не о том, что функциональности такой нет, это само собой разумеется

я о том, что НД, отображаемый гридом, может иметь меньшее число полей, чем число копируемых полей

что толку вставлять в грид что-то там, если вставляемые значения должны фактически быть зафиксированы в НД ? как фиксировать "лишние" вставляемые поля ? это вызывает много вопросов ...


 
GanibalLector ©   (2004-08-04 09:37) [13]

2 KSergey
Ну дык в форуме...тема:Delphi


 
KSergey ©   (2004-08-04 10:13) [14]

> [12] Digitman ©   (04.08.04 09:25)
> что толку вставлять в грид что-то там, если вставляемые
> значения должны фактически быть зафиксированы в НД ? как
> фиксировать "лишние" вставляемые поля ? это вызывает много
> вопросов ...

Призаться, вижу 2 пути решения проблемы, без замудривания (речь идет о случае, когда каждая колонка грида соотв. полю DataSet, да еще и редактируемому; для простоты):

1.Послать пользователя "не совпадает вормат вставляемых и ..."
2.Что не уместилось - ну и фиг с ним. Пользователь сам должен понимать, что если некуда вставлять - то логично, что вставляться не будет; по-моему, это выглядит вполне естественно.

Впрочем, это уже все так, слова. Обсуджать тут нечего, надо смотреть на конкретную задачу.

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


 
KSergey ©   (2004-08-04 10:15) [15]

Да, вот еще кусочек, если интересно
Он у меня в другом месте оказался

 // проверка: содержится ли в буфере обмена формат, похожий на формат таблицы
 function TestClipBoardTable: Boolean;
 var
   s: String;
   nCF_XLTable: Integer;
   nPos, nLen: Integer;
 begin
   nCF_XLTable := RegisterClipboardFormat (PChar("XLTable"));
   Result := Clipboard.HasFormat(nCF_XLTable);  // если есть такой формат в буфере - там точно таблица
   if NOT Result AND Clipboard.HasFormat(CF_TEXT) then
   begin
     s := Clipboard.AsText;
     Result := Pos(#9, s) > 0;  // если присутствует табуляция - однозначно считаем, что в буфере - таблицы (табуляция - разделитель столбцов)
     if NOT Result then
     begin
       nPos := Pos(#13, s); // если присутствует #13
       Result := nPos > 0;  // и это не последний символ - подозрение на таблицу
       if Result then       // уточним:
       begin
         nLen := Length(s);
         if nPos = nLen-1 then       // если это предпоследний символ -
           Result := s[nLen] > " ";  // то следующий за ним должен быть буквой (а не #10, что вероятно)
       end;
     end;
   end
   else
     Result := FALSE;
 end;



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2004.08.22;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.52 MB
Время: 0.074 c
3-1090482264
nik7777
2004-07-22 11:44
2004.08.22
Вопрос по ODBC для Lotus-Notes6


3-1090915718
MORA
2004-07-27 12:08
2004.08.22
связанные таблицы


8-1085508092
xman
2004-05-25 22:01
2004.08.22
Canvas


3-1091385437
Dot
2004-08-01 22:37
2004.08.22
Сортировка по критериям


1-1091791595
dizrov
2004-08-06 15:26
2004.08.22
диалог выбора директории





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский