доброго дня имеются две колонки в Excel. Необходимо вывести куда нибудь на форму две таблицы. Значение ячейки "111" в первой таблице нужно оформить в виде выпадающего списка, значения для которого берутся из первой колонки в Excel. Аналогично для "222", только значения берутся из второй колонки. Все остальные ячейки вычисляются по формулам, в зависимости от значений ячеек "111" и "222". Вопрос: какой тут компонент использовать, чтобы можно было так выводить на форму?
хм, видимо что то делаю не так. Не добавляются строки в ComboBox
var Form1: TForm1; E,Sheet:variant; iRow, iClm: integer;
implementation
{$R *.dfm}
procedure TForm1.StringGrid1SelectCell(Sender: TObject; ACol, ARow: Integer; var CanSelect: Boolean); var R : TRect; begin if ((ACol = 1) AND (ARow <> 0)) then begin {Размер и расположение combobox подгоняем под ячейку} {combobox должен быть в первой строке во втором столбце} R := StringGrid1.CellRect(ACol, ARow); R.Left := R.Left + StringGrid1.Left; R.Right := R.Right + StringGrid1.Left; R.Top := R.Top + StringGrid1.Top; R.Bottom := R.Bottom + StringGrid1.Top; ComboBox1.Left := R.Left + 1; ComboBox1.Top := R.Top + 1; ComboBox1.Width := (R.Right + 1) - R.Left; ComboBox1.Height := (R.Bottom + 1) - R.Top; {Показываем combobox} ComboBox1.Visible := True; ComboBox1.SetFocus; end; CanSelect := True; end;
procedure TForm1.FormCreate(Sender: TObject); var i : integer; begin {Высоту у combobox не получится установить, поэтому мы будем} {подгонять размер у грида под размер combobox!} StringGrid1.DefaultRowHeight := ComboBox1.Height; {Скрываем combobox} ComboBox1.Visible := False; StringGrid1.ColWidths[0]:=40; StringGrid1.ColWidths[1]:=300; StringGrid1.ColWidths[2]:=110; StringGrid1.ColWidths[3]:=110; StringGrid1.ColWidths[4]:=110; E:=CreateOleObject('Excel.Application'); E.WorkBooks.Open('C:\\123.xlsx'); E.WorkBooks.item [1].Activate; Sheet:=E.WorkBooks.item [1].Sheets.item[1]; iRow := Sheet.UsedRange.Row + Sheet.UsedRange.Rows.Count - 1; //последняя заполненая строка iClm := Sheet.UsedRange.Column + Sheet.UsedRange.Columns.Count - 1; //последний заполненый столбец for i:=1 to iRow do ComboBox1.Items.Add(Sheet.Cells[i,1].Text); ... end;
procedure TForm1.ComboBox1Change(Sender: TObject); begin {Получаем выбранный элемент из ComboBox и помещаем его в грид} StringGrid1.Cells[StringGrid1.Col, StringGrid1.Row] := ComboBox1.Items[ComboBox1.ItemIndex]; ComboBox1.Visible := False; StringGrid1.SetFocus; end;
procedure TForm1.ComboBox1Exit(Sender: TObject); begin {Получаем выбранный элемент из ComboBox и помещаем его в грид} StringGrid1.Cells[StringGrid1.Col, StringGrid1.Row] := ComboBox1.Items[ComboBox1.ItemIndex]; ComboBox1.Visible := False; StringGrid1.SetFocus; end;
спасибо, сработало а можно еще вопрос: событие OnClick срабатывает при выборе одного из значений из списка, OnExit - при выходе из ComboBox. Зачем в обеих случаях нужен одинаковый кусок кода? Одного не достаточно?
{Получаем выбранный элемент из ComboBox и помещаем его в грид} StringGrid1.Cells[StringGrid1.Col, StringGrid1.Row] := ComboBox1.Items[ComboBox1.ItemIndex]; ComboBox1.Visible := False; StringGrid1.SetFocus;
чтож за беда такая с этой таблицей хочу вставить в соседнюю ячейку число, соответствующее выбранному в ComboBox. Пишу так:
procedure TForm1.ComboBox1Exit(Sender: TObject); begin {Получаем выбранный элемент из ComboBox и помещаем его в грид} StringGrid1.Cells[StringGrid1.Col, StringGrid1.Row] := ComboBox1.Items[ComboBox1.ItemIndex]; StringGrid1.Cells[StringGrid1.Col, StringGrid1.Row+1]:=Sheet.Cells[StringGrid1.Col,2].Text; ComboBox1.Visible := False; StringGrid1.SetFocus; end;
procedure TForm1.ComboBox1Click(Sender: TObject); begin {Получаем выбранный элемент из ComboBox и помещаем его в грид} StringGrid1.Cells[StringGrid1.Col, StringGrid1.Row] := ComboBox1.Items[ComboBox1.ItemIndex]; StringGrid1.Cells[StringGrid1.Col, StringGrid1.Row+1]:=Sheet.Cells[StringGrid1.Col,2].Text; ComboBox1.Visible := False; StringGrid1.SetFocus; end;
событие OnClick срабатывает при выборе одного из значений из списка, OnExit - при выходе из ComboBox. Зачем в обеих случаях нужен одинаковый кусок кода?
И у меня тоже вопрос: а кто вообще изначально говорил про OnClick? Там был OnChange вообще-то. OnClick - это уже твоя придумка.
Не нравится дублирование кода - вынеси этот код в отдельную процедуру и вызывай по обоим событиям.
И у меня тоже вопрос: а кто вообще изначально говорил про OnClick? Там был OnChange вообще-то. OnClick - это уже твоя придумка.
прошу прощения, действительно мое. P.S если еще будут вопросы про этот же StringGrid или ComboBox, можно писать в эту же тему, или надо создавать новую?
после выбора строки в ComboBox, выбранная строка вставляется в ячейку, и курсор переход на след ячейку вниз, и соответственно опять раскрывается ComboBox. Можно ли запретить такой автоматический переход? В свойствах StringGrida не нашел
после выбора строки в ComboBox, выбранная строка вставляется в ячейку, и курсор переход на след ячейку вниз
Не воспроизводится. Может, ты еще что-нибудь добавлял в свойства ComboBox-а? Очень похоже, что у тебя происходит не одинарный, а двойной клик для выбора элемента.
Вообще не должно быть такого перехода, попробуй на чистом гриде, или даже на этом же, введи данные в обычную ячейку (без комбобокса), и нажми Enter - фокус останется на этой же ячейке.
Не воспроизводится. Может, ты еще что-нибудь добавлял в свойства ComboBox-а? Очень похоже, что у тебя происходит не одинарный, а двойной клик для выбора элемента.
Вообще не должно быть такого перехода, попробуй на чистом гриде, или даже на этом же, введи данные в обычную ячейку (без комбобокса), и нажми Enter - фокус останется на этой же ячейке.
да, действительно, на чистом гриде все именно так работает. А на том гриде почему то по другому. Непонятно почему. В комбобоксе только два события описаны: OnChange и OnExit. Срабатывает на одинарное нажатие. Других свойств вроде не добавлял
Добавлено через 6 мин. гм, попытаюсь объяснить. После клика на ячейке раскрывается список, выбираем строку, строка вставляется в ячейку. Но, почему то как будто кнопка мыши остается нажатой и удерживаемой, как при выделении. Поэтому, при наведении курсора на другую ячейку, срабатывает событие одинарного клика и раскрывается комбобокс. Это происходит из-за комбобкса, вставленного в ячейку?
У меня не происходит выделения другой ячейки, вот в чем проблема. Закрывается комбобокс и фокус остается на ячейке, в которую было внесено значение. А я ведь скопировал в точности твой код. Может, от версии Дельфи зависит (в более новой чего-нибудь поправили, например)? У меня XE2, могу чуть позже на 2009-ой проверить.
У меня не происходит выделения другой ячейки, вот в чем проблема. Закрывается комбобокс и фокус остается на ячейке, в которую было внесено значение. А я ведь скопировал в точности твой код. Может, от версии Дельфи зависит (в более новой чего-нибудь поправили, например)? У меня XE2, могу чуть позже на 2009-ой проверить.
странное поведение. У меня Delphi 7. Может скинуть папку с файлами проекта?
Добавлено через 4 мин. хотя, может и кода хватит
var Form1: TForm1; E,Sheet, E2,Sheet2:variant; iRow, iClm, iRow2, iClm2: integer;
implementation
{$R *.dfm}
procedure TForm1.StringGrid1SelectCell(Sender: TObject; ACol, ARow: Integer; var CanSelect: Boolean); var R : TRect; begin if (ACol = 1) and (ARow <> 0) then begin R := StringGrid1.CellRect(ACol, ARow); OffsetRect(R, StringGrid1.Left, StringGrid1.Top); ComboBox1.Left := R.Left + 1; ComboBox1.Top := R.Top + 1; ComboBox1.Width := (R.Right + 1) - R.Left; ComboBox1.Height := (R.Bottom + 1) - R.Top; {Показываем combobox} ComboBox1.Visible := True; ComboBox1.SetFocus; ComboBox1.DroppedDown := true; // <--- end; CanSelect := True; end;
procedure TForm1.FormCreate(Sender: TObject); var i : integer; begin {Высоту у combobox не получится установить, поэтому мы будем} {подгонять размер у грида под размер combobox!} StringGrid1.DefaultRowHeight := ComboBox1.Height; StringGrid2.DefaultRowHeight := ComboBox2.Height; {Скрываем combobox} ComboBox1.Visible := False; ComboBox1.Style := csDropDownList; ComboBox2.Visible := False; ComboBox2.Style := csDropDownList; StringGrid1.ColWidths[0]:=40; StringGrid1.ColWidths[1]:=300; StringGrid1.ColWidths[2]:=110; StringGrid1.ColWidths[3]:=110; StringGrid1.ColWidths[4]:=110; StringGrid2.ColWidths[0]:=40; StringGrid2.ColWidths[1]:=300; StringGrid2.ColWidths[2]:=60; StringGrid2.ColWidths[3]:=120; StringGrid2.ColWidths[4]:=140; StringGrid2.ColWidths[5]:=140; StringGrid2.ColWidths[6]:=140; StringGrid3.ColWidths[0]:=40; StringGrid3.ColWidths[1]:=300; StringGrid3.ColWidths[2]:=110; StringGrid3.ColWidths[3]:=110; StringGrid3.ColWidths[4]:=110; E:=CreateOleObject('Excel.Application'); E.WorkBooks.Open('C:\\1.xlsx'); E.WorkBooks.item [1].Activate; Sheet:=E.WorkBooks.item [1].Sheets.item[1]; E2:=CreateOleObject('Excel.Application'); E2.WorkBooks.Open('C:\\2.xlsx'); E2.WorkBooks.item [1].Activate; Sheet2:=E2.WorkBooks.item [1].Sheets.item[1]; iRow := Sheet.UsedRange.Row + Sheet.UsedRange.Rows.Count - 1; //последняя заполненая строка iClm := Sheet.UsedRange.Column + Sheet.UsedRange.Columns.Count - 1; //последний заполненый столбец iRow2 := Sheet2.UsedRange.Row + Sheet2.UsedRange.Rows.Count - 1; //последняя заполненая строка iClm2 := Sheet2.UsedRange.Column + Sheet2.UsedRange.Columns.Count - 1; //последний заполненый столбец ComboBox1.DropDownCount:=iRow; for i:=1 to iRow do ComboBox1.Items.Add(Sheet.Cells[i,1].Text); ComboBox2.DropDownCount:=iRow2; for i:=1 to iRow2 do ComboBox2.Items.Add(Sheet2.Cells[i,1].Text); end;
procedure TForm1.ComboBox1Exit(Sender: TObject); begin {Получаем выбранный элемент из ComboBox и помещаем его в грид} if ComboBox1.ItemIndex<>-1 then begin StringGrid1.Cells[StringGrid1.Col, StringGrid1.Row] := ComboBox1.Items[ComboBox1.ItemIndex]; StringGrid1.Cells[StringGrid1.Col+1, StringGrid1.Row]:=Sheet.Cells[ComboBox1.ItemIndex+1,2].Text; StringGrid1.RowCount:=StringGrid1.RowCount+1; end; ComboBox1.Visible := False; StringGrid1.SetFocus; ComboBox1.ItemIndex:=-1; end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin E.Workbooks[1].Close; E:=Unassigned; E2.Workbooks[1].Close; E2:=Unassigned; end;
procedure TForm1.StringGrid1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); var i,j: integer; begin if Key=vk_delete then begin StringGrid1.Rows[StringGrid1.Row].Clear; for i:=StringGrid1.Row to StringGrid1.RowCount-1 do begin for j:=0 to StringGrid1.ColCount do begin StringGrid1.Cells[j,i]:=StringGrid1.Cells[j,i+1] end; end; if StringGrid1.RowCount>2 then StringGrid1.RowCount:=StringGrid1.RowCount-1; end; end;
procedure TForm1.ComboBox1Change(Sender: TObject); begin {Получаем выбранный элемент из ComboBox и помещаем его в грид} if ComboBox1.ItemIndex<>-1 then begin StringGrid1.Cells[StringGrid1.Col, StringGrid1.Row] := ComboBox1.Items[ComboBox1.ItemIndex]; StringGrid1.Cells[StringGrid1.Col+1, StringGrid1.Row]:=Sheet.Cells[ComboBox1.ItemIndex+1,2].Text; end; ComboBox1.Visible := False; StringGrid1.SetFocus; end;
procedure TForm1.ComboBox2Change(Sender: TObject); begin {Получаем выбранный элемент из ComboBox и помещаем его в грид} if ComboBox2.ItemIndex<>-1 then begin StringGrid2.Cells[StringGrid2.Col, StringGrid2.Row] := ComboBox2.Items[ComboBox2.ItemIndex]; StringGrid2.Cells[StringGrid2.Col+2, StringGrid2.Row]:=Sheet2.Cells[ComboBox2.ItemIndex+1,2].Text; end; ComboBox1.Visible := False; StringGrid1.SetFocus; end;
procedure TForm1.ComboBox2Exit(Sender: TObject); begin {Получаем выбранный элемент из ComboBox и помещаем его в грид} if ComboBox2.ItemIndex<>-1 then begin StringGrid2.Cells[StringGrid2.Col, StringGrid2.Row] := ComboBox2.Items[ComboBox2.ItemIndex]; StringGrid2.Cells[StringGrid2.Col+2, StringGrid2.Row]:=Sheet2.Cells[ComboBox2.ItemIndex+1,2].Text; StringGrid2.RowCount:=StringGrid2.RowCount+1; end; ComboBox2.Visible := False; StringGrid2.SetFocus; ComboBox2.ItemIndex:=-1; end;
procedure TForm1.StringGrid2SelectCell(Sender: TObject; ACol, ARow: Integer; var CanSelect: Boolean); var R : TRect; begin if (ACol = 1) and (ARow <> 0) then begin R := StringGrid2.CellRect(ACol, ARow); OffsetRect(R, StringGrid2.Left, StringGrid2.Top); ComboBox2.Left := R.Left + 1; ComboBox2.Top := R.Top + 1; ComboBox2.Width := (R.Right + 1) - R.Left; ComboBox2.Height := (R.Bottom + 1) - R.Top; {Показываем combobox} ComboBox2.Visible := True; ComboBox2.SetFocus; ComboBox2.DroppedDown := true; // <--- end; CanSelect := True;
end;
procedure TForm1.StringGrid2KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); var i,j: integer; begin if Key=vk_delete then begin StringGrid2.Rows[StringGrid2.Row].Clear; for i:=StringGrid2.Row to StringGrid2.RowCount-1 do begin for j:=0 to StringGrid2.ColCount do begin StringGrid2.Cells[j,i]:=StringGrid2.Cells[j,i+1]; end; end; if StringGrid2.RowCount>2 then StringGrid2.RowCount:=StringGrid2.RowCount-1; end; end;