错误的数据从TListbox移动到TStringGrid

时间:2012-12-12 06:00:48

标签: delphi delphi-7

我正在研究Delphi 7.我有一个TListBox和一个带有两列的TStringGrid(没有固定的行或列)。我在TListBox中有如下数据:

可用元素 - a123(a123) 可用元素 - a1234(a1234) 可用元素 - a12345(a12345)

TStringGrid的数据如下:

Column1 Column2

a1可用元素 - a1 a2可用元素 - a12

如果我选择TListbox中的第一项,即a123并执行以下按钮点击事件程序,则最后一项数据即a12345将被移入网格。

在下面的代码中,是否有人可以将重点放在我做错的事情上。下面的代码将TListbox中的seleted项移动到TStringgird的两列:

procedure TForm1.btnMoveLeftClick(Sender: TObject);
var
  sString : String;
  i : Integer;
begin
  for i := 0 to ListBox1.Items.Count - 1 do
  begin
      {-- Is this status selected? --}
      if ListBox1.Selected[i] then
      begin
        sString := Trim(ListBox1.Items[i]);

        {-- Delete selected status. --}
          ListBox1.Items.Delete (i);

        if ((grdVFormDetails.RowCount >= 1) And (Trim(grdVFormDetails.Cells[0, 0]) <> EmptyStr)) then
          grdVFormDetails.RowCount := grdVFormDetails.RowCount+1;

        grdVFormDetails.Cols[1].Add(Copy(sString, 1, Pos('(', sString) - 1));

        sString := Copy(sString, Pos('(', sString) + 1, Length(sString));
        sString := Copy(sString, Pos('(', sString) + 1, Length(sString) - 1);

        grdVFormDetails.Cols[0].Add(sString);


        break;
      end;
  end;
end;

4 个答案:

答案 0 :(得分:2)

永远不要删除FOR循环中的TList项。

这一行的问题:

  ListBox1.Items.Delete (i);

循环从i:= 0变为2.项目 - 0被选中并删除它。我们下次重复的是什么? i = 1但是这里只剩下2个项目而不是3个(所有后续项目都被移动),我指向最后一个项目而不是第二个项目。在i = 3的下一次重复时,我们将得到“Index out of bound”错误。您应该仅在FOR循环后删除Item以避免此问题。

procedure TForm1.btnMoveLeftClick(Sender: TObject);
var
  sString : String;
  i : Integer;
  k: integer;
begin
  k:=-1; 
  for i := 0 to ListBox1.Items.Count - 1 do
  begin
      {-- Is this status selected? --}
      if ListBox1.Selected[i] then
      begin
        sString := Trim(ListBox1.Items[i]);

        {-- Delete selected status. --}
          k:=i;         

        if ((grdVFormDetails.RowCount >= 1) And (Trim(grdVFormDetails.Cells[0, 0]) <> EmptyStr)) then
          grdVFormDetails.RowCount := grdVFormDetails.RowCount+1;

        grdVFormDetails.Cols[1].Add(Copy(sString, 1, Pos('(', sString) - 1));

        sString := Copy(sString, Pos('(', sString) + 1, Length(sString));
        sString := Copy(sString, Pos('(', sString) + 1, Length(sString) - 1);

        grdVFormDetails.Cols[0].Add(sString);


        break;
      end;
  end;
  if k>=0 then  ListBox1.Items.Delete (k);

end;

答案 1 :(得分:1)

假设您要解析输入字符串,如下所示:

'Some text (comment) etc. (12345)'

进入一个带有修剪字符串的部分,从输入字符串的开头到第一个左括号(从头到尾)得到一个这样的值:

'Some text (comment) etc.'

和输入字符串的最后一个括号内的字符串:

'12345'

如果是这样,您可以使用以下代码。请注意,预计将通过右括号终止列表框项目。如果需要,您可以查看此代码的commented version或下载sample project

以下是将焦点项目从列表框移动到字符串网格的部分:

procedure TForm1.MoveLeftButtonClick(Sender: TObject);
var
  S: string;
  I: Integer;
  ItemID: string;
  ItemText: string;
begin
  if ListBox1.ItemIndex = -1 then
    Exit;

  S := ListBox1.Items[ListBox1.ItemIndex];
  for I := Length(S) - 1 downto 1 do
  begin
    if S[I] = '(' then
    begin
      ItemID := Trim(Copy(S, I + 1, Length(S) - I - 1));
      ItemText := Trim(Copy(S, 1, I - 1));
      with StringGrid1 do
      begin
        if (Cells[0, RowCount - 1] <> '') and
          (Cells[1, RowCount - 1] <> '')
        then
          RowCount := RowCount + 1;
        Cells[0, RowCount - 1] := ItemID;
        Cells[1, RowCount - 1] := ItemText;
      end;
      ListBox1.Items.Delete(ListBox1.ItemIndex);
      Break;
    end;
  end;
end;

以下是将所选行从字符串网格移动到列表框的部分:

procedure TForm1.MoveRightButtonClick(Sender: TObject);
var
  I: Integer;
  RowIndex: Integer;
begin
  RowIndex := StringGrid1.Selection.Top;
  if (StringGrid1.Cells[0, RowIndex] <> '') and
    (StringGrid1.Cells[1, RowIndex] <> '') then
  begin
    ListBox1.Items.Add(
      Trim(StringGrid1.Cells[1, RowIndex]) + ' (' +
      Trim(StringGrid1.Cells[0, RowIndex]) + ')'
    );
    for I := RowIndex to StringGrid1.RowCount - 2 do
      StringGrid1.Rows[I].Assign(StringGrid1.Rows[I + 1]);
    if StringGrid1.RowCount > 1 then
      StringGrid1.RowCount := StringGrid1.RowCount - 1
    else
    begin
      StringGrid1.Cells[0, 0] := '';
      StringGrid1.Cells[1, 0] := '';
    end;
  end;
end;

答案 2 :(得分:0)

我目前没有安装Delphi,但据我记得,如果ListBox1.Selected [i]则不会给你正确的结果。你需要先得到这个项目, 他们检查项目是否被选中。

答案 3 :(得分:0)

如果ListBox中没有多重选择,最好使用ItemIndex属性,该属性为您提供所选项目的索引,因此您无需循环检查列表中的所有项目。 / p>

像这样:

procedure TForm1.btnMoveLeftClick(Sender: TObject);
var
  sString : String;
  i : Integer;
begin
  if ListBox1.ItemIndex <> -1 then
  begin
    sString := Trim(ListBox1.Items[ListBox1.ItemIndex]);
    //do all your processing here
    //and at the end:
    ListBox1.Items.Delete(ListBox1.ItemIndex);
  end
end;