Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 27.10.2016, 05:38   #1
Kostya12
Пользователь
 
Регистрация: 29.09.2016
Сообщений: 29
По умолчанию String grid в Delphi.

В общем есть программа ,находит дубликаты значений вот код.
Код:
unit class_fMain;

interface

uses
  Windows,
  Messages,
  SysUtils,
  Classes,
  Variants,
  Graphics,
  Controls,
  Forms,
  Dialogs,
  Grids,
  ComObj,
  StdCtrls;



type
  TfMain = class(TForm)
    sgExcel: TStringGrid;
    btnOpenFile: TButton;
    OpenDlg: TOpenDialog;
    btnFind: TButton;
    Label1: TLabel;
    procedure btnOpenFileClick(Sender: TObject);
    procedure btnFindClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  fMain: TfMain;

implementation

{$R *.dfm}

procedure Xls_Open(XLSFile:string; Grid: TStringGrid);
//Считывает Excel в StringGrid.
const
  xlCellTypeLastCell = $0000000B;
var
  ExlApp, Sheet: OLEVariant;
  i, j, r, c: Integer;
begin
  ExlApp := CreateOleObject('Excel.Application');
  try
    ExlApp.Visible := false;
    ExlApp.Workbooks.Open(XLSFile);
    Sheet := ExlApp.Workbooks[ExtractFileName(XLSFile)].WorkSheets[1];
    Sheet.Cells.SpecialCells(xlCellTypeLastCell, EmptyParam).Activate;
    r := ExlApp.ActiveCell.Row;
    c := ExlApp.ActiveCell.Column;
    Grid.RowCount:=r;
    Grid.ColCount:=c;
     for j:= 1 to r do
       for i:= 1 to c do
         Grid.Cells[i-1,j-1]:= sheet.cells[j,i];
  finally
    ExlApp.Quit;
    ExlApp := Unassigned;
    Sheet := Unassigned;
    ShowMessage('Загрузка завершена ,можно работать с файлом');
  end;
end;


procedure AutoSizeGridColumn(Grid : TStringGrid; Column : Integer);
//Авторазмер колонок StringGrid под ширину текста.
var
  I : Integer;
  Temp : Integer;
  Max : Integer;
begin
  Max := 0;
  for i := 0 to (Grid.RowCount - 1) do
  begin
    Temp := Grid.Canvas.TextWidth(Grid.Cells[Column, I]);
    if Temp > Max
      then Max := Temp;
  end;
  Grid.ColWidths[Column] := Max + Grid.GridLineWidth + 10;
end;


procedure TfMain.btnOpenFileClick(Sender: TObject);
var
  X: Integer;
begin
  OpenDlg.InitialDir:=ExtractFilePath(ParamStr(0));
  if OpenDlg.Execute then
    begin
      Xls_Open(OpenDlg.Files[0], sgExcel);
      for x := 0 to sgExcel.ColCount-1 do
        AutoSizeGridColumn(sgExcel, x);
    end;
end;

procedure TfMain.btnFindClick(Sender: TObject);
type
  Rec = record
    sgLine: Integer;
    cData: String;
    sData: String;
    fCount: Integer;
end;

var
  x: Integer;
  cache: array of Rec;

procedure FillData(Col1, Col2: String; Addr: Integer);
var
  I: Integer;
  Found: Boolean;
begin
  Found:=False;
  for I := Low(cache) to High(Cache) do
    begin
      if
        (Cache[i].cData = trim(lowercase(Col1))) and
        (Cache[i].sData = trim(lowercase(Col2)))
      then
        begin
          Inc(Cache[i].fCount);
          Found:=True;
          Break;
        end;
    end;
  if not Found then
    begin
      SetLength(Cache, Length(Cache)+1);
      Cache[Length(Cache)-1].cData:=Trim(Lowercase(Col1));
      Cache[Length(Cache)-1].sData:=Trim(Lowercase(Col2));
      Cache[Length(Cache)-1].fCount:=1;
      Cache[Length(Cache)-1].sgLine:=Addr;
    end;
end;

begin
  //Отфильтруем нужные значения по  по 3 и 7-й колонке одновременно.
  for x := 1 to sgExcel.RowCount-1 do FillData(sgExcel.Cells[3,x], sgExcel.Cells[7,x], x);
  //Покажем где у нас нужные значения.
  for x := Low(cache) to High(cache) do
    if cache[x].fCount > 1
      then MessageBox
        (
          Handle,
          pChar(Format('Значения: [%d],Номер документа %s: , количество: [%d]',
            [
              cache[x].sgLine,
              cache[x].cData + ' ' +  cache[x].sData,
              cache[x].fCount
            ])),
          pChar(fMain.Caption),
          MB_ICONINFORMATION or MB_OK
        );
end;



end.
.
Нужно в string поместить ответ получившихся значений. Вот часть этого кода отвечающее за неудобное окно.
Код:
begin
  //Отфильтруем нужные значения по  по 3 и 7-й колонке одновременно.
  for x := 1 to sgExcel.RowCount-1 do FillData(sgExcel.Cells[3,x], sgExcel.Cells[7,x], x);
  //Покажем где у нас нужные значения.
  for x := Low(cache) to High(cache) do
    if cache[x].fCount > 1
      then MessageBox
        (
          Handle,
          pChar(Format('Значения: [%d],Номер документа %s: , количество: [%d]',
            [
              cache[x].sgLine,
              cache[x].cData + ' ' +  cache[x].sData,
              cache[x].fCount
            ])),
          pChar(fMain.Caption),
          MB_ICONINFORMATION or MB_OK
        );
end;



end.
Вот как я думаю должно быть
Код:
for x := Low(cache) to High(cache) do
    if cache[x].fCount > 1
    begin
    StringGrid1.cell[0,x - Low(cache)] := inttostr(cache[x].sgLine);
    StringGrid1.cell[1,x - Low(cache)] := cache[x].cData + ' ' +  cache[x].sData;
    StringGrid1.cell[2,x - Low(cache)] := inttostr(cache[x].sgCount);
    end;
В принципе я понял надо создать StringGrid и циклом зафигачить туда эти данные ровно в том месте, где у меня раньше выводился этот MessageBox. Но как это сделать?
Kostya12 вне форума Ответить с цитированием
Старый 27.10.2016, 09:08   #2
phomm
personality
Старожил
 
Аватар для phomm
 
Регистрация: 28.04.2009
Сообщений: 2,882
По умолчанию

Всё правильно на первый взгляд, только не StringGrid1.cell , а StringGrid1.Cells .
Грид разместить где удобно, при необходимости установить свойства FixedColCount FixedRowCount в 0. До цикла установить нужное количество колонок (ColCount = 3), в цикле сделать рост грида в "высоту" Grid.RowCount := Max(Grid.RowCount, x - Low(cache) + 1); (для Max надо в uses добавить Math).
phomm вне форума Ответить с цитированием
Старый 27.10.2016, 10:58   #3
Kostya12
Пользователь
 
Регистрация: 29.09.2016
Сообщений: 29
По умолчанию

хммм ну так понял должно в коде выглядить вот так
Код:
procedure TfMain.StringGrid1Click(Sender: TObject);
var;/здесь ставятся каике-то переменные
begin
for x := Low(cache) to High(cache) do
    if cache[x].fCount > 1
    begin
    StringGrid1.cells[0,x - Low(cache)] := inttostr(cache[x].sgLine);
    StringGrid1.cells[1,x - Low(cache)] := cache[x].cData + ' ' +  cache[x].sData;
    StringGrid1.cells[2,x - Low(cache)] := inttostr(cache[x].sgCount);//это и есть основной код
    end;
end;

end.
Kostya12 вне форума Ответить с цитированием
Старый 28.10.2016, 04:38   #4
Kostya12
Пользователь
 
Регистрация: 29.09.2016
Сообщений: 29
По умолчанию Новый способ

Я тут подумал можно сделать так
1. Делаете отдельную форму.
2. Делаете на ней SG.
3. Добавляете в Record который обслуживает дубли - еще одно измерение (номера строк первого SG) в котором будут фиксироваться строки.
4. Вместо MessageBox вставляете заполнение SG на второй форме. И не надо извращаться с Max, оно зачем тут вообще? Прстой вывод строки и Inc(SG.RowCount, 1);
Kostya12 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
string grid Lukashi Общие вопросы Delphi 7 27.05.2011 09:42
string grid... ilushka2306 Помощь студентам 1 18.03.2011 23:32
string grid toxaxa Общие вопросы Delphi 8 17.06.2010 14:09
Вопрос по Delphi(string grid) Slava-hacker32 Помощь студентам 2 04.05.2010 10:55
String Grid в VC++ Аlex Общие вопросы C/C++ 1 30.01.2009 22:48