Впервые в жизни столкнулся с такой задачкой, посмотрел на подобе вроде нету. Мне нужно выдернуть данные из ексельного файла со сложной структурой данные, которые могут быть не нормированы, т.е. не ограниченны по длине. Запись произвести в стринггрид или дбгрид. Нужны следующие поля А 5 или 10, т.е. те в которых есть надпись НОД 3, все D с названиями, причем коды нужно писать отдельно, все H соответствующие D, и все B с датами месяца и года в разные ячейки. Пробовал фильтрами, но это только отсеивает, а не прописывает. Надо прописать, что бы после можно было портировать данные эти в ораклинную базу. Меня еще останавливает, то что нельзя задать ячейки железно, на тот случай, если таблица пополнится новыми позициями
volvo
17.12.2009 0:39
Я, может, чего-то не понимаю, но если ты знаешь, что в ячейке A5 находится текст "НОД 3", зачем тебе читать это поле? Я тебе и так скажу, что оно содержит. Не поверишь, но оно содержит "НОД 3".
Цитата
все D с названиями
Ну, и проходи по ячейкам "D1" .. "Dдо_посинения", проверяй на пустоту и если не пусто - то нашел, что тебе нужно, можешь отсекать все после последнего пробела и делить информацию на Название и Код. Поскольку при этом ты знаешь номер строки, из которой это все читалось, то элементарно вытягивается содержимое соответствующих полей из столбцов B и H. В чем проблема, я не пойму?
Оракла не держу. Если интересно - могу набросать программу, которая из присоединенного тобой файла выдерет всю нужную информацию (Название/Код/Что_там_у_тебя_в_столбце_B/Дебет), и занесет ее в StringGrid на форме, или в базу MS Access... Только что там с A5/A10 - надо бы уточнить...
Atreides
17.12.2009 0:58
Я писал вот так...
unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, Grids, DBGrids, Menus, ComObj; type TForm1 = class(TForm) MainMenu1: TMainMenu; N1: TMenuItem; N2: TMenuItem; N3: TMenuItem; StringGrid1: TStringGrid; GroupBox1: TGroupBox; GroupBox2: TGroupBox; Button1: TButton; Button2: TButton; procedure N3Click(Sender: TObject); procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} function Xls_To_StringGrid(AGrid: TStringGrid; AXLSFile: string): Boolean; const xlCellTypeLastCell = $0000000B; var XLApp, Sheet: OLEVariant; RangeMatrix: Variant; x, y, k, r: Integer; begin Result := False; // Create Excel-OLE Object XLApp := CreateOleObject('Excel.Application'); try // Hide Excel XLApp.Visible := False; // Open the Workbook XLApp.Workbooks.Open(AXLSFile); // Sheet := XLApp.Workbooks[1].WorkSheets[1]; Sheet := XLApp.Workbooks[ExtractFileName(AXLSFile)].WorkSheets[1]; // In order to know the dimension of the WorkSheet, i.e the number of rows // and the number of columns, we activate the last non-empty cell of it Sheet.Cells.SpecialCells(xlCellTypeLastCell, EmptyParam).Activate; // Get the value of the last row x := XLApp.ActiveCell.Row; // Get the value of the last column y := XLApp.ActiveCell.Column; // Set Stringgrid's row &col dimensions. AGrid.RowCount := x; AGrid.ColCount := y; // Assign the Variant associated with the WorkSheet to the Delphi Variant RangeMatrix := XLApp.Range['A1', XLApp.Cells.Item[X, Y]].Value; // Define the loop for filling in the TStringGrid k := 1; repeat for r := 1 to y do AGrid.Cells[(r - 1), (k - 1)] := RangeMatrix[K, R]; Inc(k, 1); AGrid.RowCount := k + 1; until k > x; // Unassign the Delphi Variant Matrix RangeMatrix := Unassigned; finally // Quit Excel if not VarIsEmpty(XLApp) then begin // XLApp.DisplayAlerts := False; XLApp.Quit; XLAPP := Unassigned; Sheet := Unassigned; Result := True; end; end; end; procedure TForm1.Button1Click(Sender: TObject); begin Close; end; procedure TForm1.Button2Click(Sender: TObject); begin if Xls_To_StringGrid(StringGrid1, 'D:\КОАСУФР\КОАСУФР10.xls') then
ShowMessage('Таблица была загруженна!'); end; procedure TForm1.N3Click(Sender: TObject); begin Close; end; end.
Просто "Нод"ы могут быть же после данных, как с этим быть. А можно пример как вести проверку? Да и программку хотелось бы все глянуть, интересно.
volvo
17.12.2009 2:40
Цитата
А можно пример как вести проверку? Да и программку хотелось бы все глянуть, интересно.
Ну, глянь:
procedure LockGrid(Grid: TStringGrid); var i: Integer; begin for i := 0 to Pred(Grid.ColCount) do Grid.Cols[i].BeginUpdate; end;
procedure UnLockGrid(Grid: TStringGrid); var i: Integer; begin for i := 0 to Pred(Grid.ColCount) do Grid.Cols[i].EndUpdate; end;
AGrid.Cells[2, 0] := 'B'; AGrid.Cells[3, 0] := 'D название'; AGrid.Cells[4, 0] := 'D код'; AGrid.Cells[5, 0] := 'H';
LockGrid(AGrid);
curr := Pred(AGrid.FixedRows); for Row := 1 to Rows do begin Range := Sheet.Range['D' + IntToStr(Row), EmptyParam]; if not VarIsEmpty(Range) then begin s := Range.Value; if (s <> '') and (Ord(s[1]) <> 160) then begin s := Trim(s); // Inc(curr); SpacePos := LastDelimiter(Char(160), s); AGrid.Cells[0, curr] := IntToStr(Row); AGrid.Cells[2, curr] := Sheet.Range['B' + IntToStr(Row), EmptyParam].Value; AGrid.Cells[3, curr] := Copy(s, 1, SpacePos - 1); AGrid.Cells[4, curr] := Copy(s, SpacePos + 1, Length(s)); AGrid.Cells[5, curr] := Sheet.Range['H' + IntToStr(Row), EmptyParam].Value; end; end; end;
UnLockGrid(AGrid); AGrid.RowCount := curr + 1; Result := True; finally if not VarIsEmpty(XLApp) then begin // XLApp.DisplayAlerts := False; XLApp.Quit; XLAPP := Unassigned; Sheet := Unassigned; end; end; end;
procedure TForm1.Button1Click(Sender: TObject); begin if XL_GetInfo(StringGrid1, 'F:\Programs\Delphi\XL\example.xls') then begin ShowMessage('Таблица была загружена!'); end; end;
Тут можно еще поубирать лишние действия, вроде многократных преобразований IntToStr одного и того же числа, можно забросить обращения к Cells под один With, будет выглядеть гораздо красивее. Но код и так работает достаточно быстро за счет того, что Грид залочен, и постоянного обновления, съедающего основное время, не происходит...
Atreides
18.12.2009 23:07
так, это понятно, а вот как мне бы отсеять из таблички данные по билетам и багажу, как выполнить проверку по значению в ячейки. и итого строки не нужны. Как вытащить данные из объединенных ячеек, типа даты? В одну табличку, все билеты, в другую багаж. И после как бы мне передавать эти данные в БД, по какому параметру? Знаю, что через SQL запросы и компоненты DataSet и SocketConnection.
volvo
18.12.2009 23:25
Цитата
а вот как мне бы отсеять из таблички данные по билетам и багажу
Можно по-русски? Что откуда отсеять? Что получить надо и ГДЕ? Если у тебя задача что-то сделать непосредственно в XL-файле, то при чем тут вообще Дельфи? VBA тебе в помощь, и делай все, что нужно... А потом сделаешь экспорт в БД (наверняка это возможно), Дельфи вообще не нужно ни для чего, кроме как запустить VBA-код. Если же у тебя задача вытянуть из XLS определенную информацию - то что за проблема? Как обращаться к ячейке я тебе показал... Ты же знаешь, что у тебя каждая графа означает, я-то этого не знаю, названия "Дата прово" и "Ссылочный № до" мне ничего не говорят, например (а слово "багаж" я вообще только что от тебя в первый раз услышал, в присоединенном файле о нем - ни слуху ни духу)... Вот, к примеру, что должно быть в базе, если есть документ, присоединенный тобой к посту №1? По полям, желательно, напиши, что НАДО копировать, а чего - НЕ НАДО.
Цитата
и итого строки не нужны
Не нужны - убери строку №62...
Цитата
И после как бы мне передавать эти данные в БД, по какому параметру?
Опять за свое... У тебя данные пишутся в СтрингГрид, как хочешь, так и заливай их в базу, на кой черт тебе еще SocketConnection понадобился? Тут одного ДатаСета - за глаза...
Atreides
19.12.2009 22:11
Файл эксель я не могу сам лично править, его генерирует, как отчет информационная система. В грид я решил выводить для наглядности пользователю, а так мне нужно забрать данные из столбцов и прописать в базу. Причем надо прописывать билеты и грозобагаж в отдельные базы, остальные выписки не нужны. Строки нужны только с Датой, названием и кодом станции, НОДА ( ну там 3 или 7) и дебет. Остальное нафиг не нужно, все там итого и так далее. Трабл в том, что данные не подряд идут, а с разрывами и тем более разнородные, выходит проверку делать на содержание определенного участка. Т.е. находим строки «Билеты» и отправляем в БД содержимое из блока билеты, но только дату, код и название станции, и дебет с НОД. Так же и с грузобагажом.
Atreides
12.01.2010 21:43
А как можно получить адрес ячейки из екселя содержимое, которой удовлетворяет поисковой фразе?
Atreides
13.01.2010 0:49
т.е. мне нужно найти и сверить сумму значений в столбце (это я выполнил) со значение в ячейки А65. Но не хотелось бы железно присваивать ячейку на случай её расширения.
unit Unit1; var Form1: TForm1; // b:real; implementation
{$R *.dfm} procedure LockGrid(Grid: TStringGrid); var i: Integer; begin for i := 0 to Pred(Grid.ColCount) do Grid.Cols[i].BeginUpdate; end;
procedure UnLockGrid(Grid: TStringGrid); var i: Integer; begin for i := 0 to Pred(Grid.ColCount) do Grid.Cols[i].EndUpdate; end;
curr := Pred(AGrid.FixedRows); for Row := 1 to Rows do begin Range := Sheet.Range['B' + IntToStr(Row), EmptyParam]; if not VarIsEmpty(Range) then begin s := Range.Value; if (s <> '') and (Ord(s[1]) <> 250) then begin s := Trim(s); // Inc(curr); SpacePos := LastDelimiter(Char(160), s); //AGrid.Cells[0, curr] := IntToStr(Row); //AGrid.Cells[1, curr] := Sheet.Range['A' + IntToStr(Row), EmptyParam].Value; //AGrid.Cells[2, curr] := Sheet.Range['B' + IntToStr(Row), EmptyParam].Value; AGrid.Cells[0, curr] := Copy(s, 1, 6); // Вот это как то работает AGrid.Cells[1, curr] := Copy(s, 7, Length(s)); AGrid.Cells[2, curr] := Sheet.Range['C' + IntToStr(Row), EmptyParam].Value; AGrid.Cells[3, curr] := Sheet.Range['D' + IntToStr(Row), EmptyParam].Value; AGrid.Cells[4, curr] := Sheet.Range['E' + IntToStr(Row), EmptyParam].Value; //порешил наконец то с ячейками end; end; end;
UnLockGrid(AGrid); AGrid.RowCount := curr + 1; Result := True; finally if not VarIsEmpty(XLApp) then begin // XLApp.DisplayAlerts := False; XLApp.Quit; XLAPP := Unassigned; Sheet := Unassigned; end; end; end;
//////////////////кнопка Загрузки procedure TForm1.Button2Click(Sender: TObject); var i,j,coma:integer; deb:string; st:string; begin // SocketConnection1.Connected:=true; // SocketConnection1.AppServer.OpenBase('ora8','fs_master','fs_master'); for i := 2 to StringGrid1.RowCount - 1 do begin deb:=StringGrid1.Cells[4,i]; //избавляемся от минусов-тире if (deb[1] = '-') then deb:=copy(deb,2,length(deb)-1);
coma := pos(',',deb); // избавляемся от точки в ячейки if coma<>0 then deb[coma]:='.'; //end; SocketConnection1.Connected:=true; SocketConnection1.AppServer.openbase('ORA8','fs_master','fs'); //коннект к БД
// st:='begin delete from test where NOD=A03'+' Commit;' +' end;';;
///////////////////кнопка Выхода procedure TForm1.Button3Click(Sender: TObject); begin Close; //тупо закрытие end;
//////////////////////// не придумал название кнопки procedure TForm1.Button4Click(Sender: TObject); //var MyRange, V: OleVariant; begin // MyRange := ExcelWorksheetl.Range[‘В2', EmptyParam]; // просмотр содержимого ячейки В2 //V := MyRange.Value; //ShowMessage(V); // занесение в ячейку значения из окна Editl //MyRange.Value := Editl.Text;
end;
///////////////////////////////////кнопка Выгрузки procedure TForm1.Button1Click(Sender: TObject); var a,b:real; i:integer;
begin if XL_GetInfo(StringGrid1, 'D:\КОАСУФР\ФО7ЛОКТ.xls') then //указание пути к файлику begin a:=0; //зануляем b:=0; //зануляем for i := 2 to StringGrid1.RowCount - 1 do // шагаем, дружно вниз a:=a+StrToFloat(StringGrid1.Cells[4,i]); // продолжаем шагать по ячейкам уже a:=a*(-1); //снова минус Form1.Label4.caption:= FloatToStr(a); //выводим на форму if a=b then //сравниваем ShowMessage('Закачка данных завершена корректно'); if a<>b then ShowMessage('Сумма итого расходиться с суммами по станциям, повторите закачку'); end; // begin // ShowMessage('Таблица "СводРазныхСборовПасс'); //end; end;
end.
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.