Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2 3   вперед  Ctrl      все
 Сравнение 2 файлов (.xlsx) посредством Delphi  [new]
Molchan
Member

Откуда:
Сообщений: 21
Добрый день. Задача такая, имеется 2 Excel файла с расширением .xlsx. Необходимо узнать имеется ли каждая запись первого файла во втором. В каждом файле порядка 8000 строк. Если сравнитьвать посредством OLE получается долго. Куда копать, как быть? Сильно не ругайте, новичок.
5 авг 19, 07:38    [21941799]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение 2 файлов (.xlsx) посредством Delphi  [new]
x1ca4064
Member

Откуда:
Сообщений: 996
Molchan
Если сравнитьвать посредством OLE получается долго. Куда копать, как быть?


Зависит от того, как через ОЛЕ работаете: если через Cells, это одно, а если через Range и все равно медленно, это другое.
5 авг 19, 07:48    [21941801]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение 2 файлов (.xlsx) посредством Delphi  [new]
Molchan
Member

Откуда:
Сообщений: 21
x1ca4064,

Получаю данные с ексель в массив, загружаю в StringGrid. Дальше в счетчиком по строчно проверяю..
5 авг 19, 07:49    [21941803]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение 2 файлов (.xlsx) посредством Delphi  [new]
x1ca4064
Member

Откуда:
Сообщений: 996
Molchan
x1ca4064,

Получаю данные с ексель в массив


Эту часть можно реализовать через Cells (пробегая в цикле) или через Range (сразу вариантный массив)
5 авг 19, 07:51    [21941805]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение 2 файлов (.xlsx) посредством Delphi  [new]
Molchan
Member

Откуда:
Сообщений: 21
Может есть какая то возможность запихать данные во временную таблицу и уже по этой таблице SQL запросами найти что есть, чего нет?
5 авг 19, 07:51    [21941806]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение 2 файлов (.xlsx) посредством Delphi  [new]
Molchan
Member

Откуда:
Сообщений: 21
x1ca4064,

Пример можно, если есть? Хотя бы кусок. Буду благодарен!
5 авг 19, 07:52    [21941808]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение 2 файлов (.xlsx) посредством Delphi  [new]
x1ca4064
Member

Откуда:
Сообщений: 996
Molchan
x
Пример можно, если есть? Хотя бы кусок. Буду благодарен!


Все говорят "буду..." :) Готового примера нет (точнее есть,но большой), могу подсказать, что изменить в Вашем коде.
5 авг 19, 07:59    [21941811]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение 2 файлов (.xlsx) посредством Delphi  [new]
Molchan
Member

Откуда:
Сообщений: 21
x1ca4064,

for I:= 8 to StringGrid1.RowCount do
begin
for J:= 7 to StringGrid2 do
begin
if AnsiCompareText(StringGrid1.Cells[11, i], StringGrid2.Cells[3, j] = 0) then
begin
 // выполняем действия
break;
end;
end;
end;
5 авг 19, 08:26    [21941825]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение 2 файлов (.xlsx) посредством Delphi  [new]
Molchan
Member

Откуда:
Сообщений: 21
Molchan
x1ca4064,

for I:= 8 to StringGrid1.RowCount do
begin
for J:= 7 to StringGrid2 do
begin
if AnsiCompareText(StringGrid1.Cells[11, i], StringGrid2.Cells[3, j] = 0) then
begin
 // выполняем действия
break;
end;
end;
end;


for J:= 7 to StringGrid2.RowCount do
5 авг 19, 08:27    [21941826]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение 2 файлов (.xlsx) посредством Delphi  [new]
x1ca4064
Member

Откуда:
Сообщений: 996
Molchan
x1ca4064,

for I:= 8 to StringGrid1.RowCount do
begin
for J:= 7 to StringGrid2 do
begin
if AnsiCompareText(StringGrid1.Cells[11, i], StringGrid2.Cells[3, j] = 0) then
begin
 // выполняем действия
break;
end;
end;
end;


Короче, кода нет. У Вас скорее всего, тормоза в 2 местах:
1. Получение данных - там поможет Range
2. Поиск данных - там поможет сортировка
2.5 ну и данные храните в массиве, а не в гриде.
5 авг 19, 08:33    [21941829]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение 2 файлов (.xlsx) посредством Delphi  [new]
Molchan
Member

Откуда:
Сообщений: 21
x1ca4064,

1. Данные так и есть, получаю в массив.\
2. По поводу сортировки, можете поподробней?
3. Понял, не буду грузить в грид.
5 авг 19, 08:35    [21941831]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение 2 файлов (.xlsx) посредством Delphi  [new]
x1ca4064
Member

Откуда:
Сообщений: 996
Molchan
x1ca4064,
2. По поводу сортировки, можете поподробней?


Вы решаете такую задачу: для каждой строки из Массива1 ищете, есть ли такая же в Массиве2. В текущей реализации для поска в Массиве2 Вы его просматриваете полностью (8000 операций, грубо), а если Массив2 отсортировать, можно будет использовать двоичный поиск (13 операций, примерно).
5 авг 19, 08:44    [21941836]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение 2 файлов (.xlsx) посредством Delphi  [new]
Molchan
Member

Откуда:
Сообщений: 21
x1ca4064,

Тяжело без примера :( Полезу в help..
5 авг 19, 08:52    [21941840]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение 2 файлов (.xlsx) посредством Delphi  [new]
x1ca4064
Member

Откуда:
Сообщений: 996
Molchan
x1ca4064,

Тяжело без примера :( Полезу в help..


Посмотрите TList, TStringList. У меня осталось подозрение, что тормоза могут быть и в части получения данных: проверьте скорость работы без поиска строк. С другой стороны, отсортировать можно и в Excel :)
5 авг 19, 08:56    [21941842]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение 2 файлов (.xlsx) посредством Delphi  [new]
LocksmithPC
Member

Откуда:
Сообщений: 199
Занимался когда то такой ерундой, но плюнул. Задача идиотская.

сырцы:
+

{$APPTYPE CONSOLE}

program SheetsCompare;

uses
  ActiveX, Classes, ComObj, Mainunit, SysUtils, Variants;

const
  cVector: array [0..3] of Char = (
    '?', '-', '|', '\');
    
type
  TVector = (vUnd, vRow, vCol, vRnC);

  TSheetRec = record
    fFileName: string;
    fSheetName: string;
    fRow: Integer;
    fCol: Integer;
    fVector: TVector;
    fBreakFlag: string;

    fList: TStringList;
    fError: string;
  end;

  TSheetsCompare = class(TObject)
  private
    { Private declarations }
    fMainList: TStringList;
    fResultList: TStringList;

    fSheets: array of TSheetRec;

    function LoadSheetCalc(const ASheetRec: TSheetRec): Boolean;
    function LoadSheetExcel(const ASheetRec: TSheetRec): Boolean;

    function CompareSheets: Boolean;
    function ParseParams: Boolean;
  public
    { Public declarations }
    constructor Create;
    destructor Destroy; override;

  end;

var
  hSheetsCompare: TSheetsCompare;

{ TSheetsCompare }

{ Private declarations }

function TSheetsCompare.LoadSheetCalc(const ASheetRec: TSheetRec): Boolean;
begin
  Result := False;

end;

function TSheetsCompare.LoadSheetExcel(const ASheetRec: TSheetRec): Boolean;
var
  vExcel: Variant;
  vSheet: Variant;

  sBuffer: string;

  iRow: Integer;
  iCol: Integer;

begin
  Result := False;

  vExcel := CreateOleObject('Excel.Application');
  try
    with ASheetRec do
      if FileExists(fFileName) then
        begin
          vExcel.WorkBooks.Open(FileName := fFileName, ReadOnly := True);

          vSheet := vExcel.ActiveWorkBook.ActiveSheet;

          iRow := fRow; iCol := fCol;
          sBuffer := vSheet.Cells[iRow, iCol];

          if fVector <> vUnd then
            while Trim(sBuffer) <> fBreakFlag do
              begin
                fMainList.Add(sBuffer);
                fList.Add(sBuffer);

                if fVector = vRow then
                  Inc(iRow);

                if fVector = vCol then
                  Inc(iCol);

                if fVector = vRnC then
                  begin
                    Inc(iRow);
                    Inc(iCol);
                  end;

                sBuffer := vSheet.Cells[iRow, iCol];
              end;

          vSheet := Unassigned;

          vExcel.WorkBooks.Close;
        end
      else
        fResultList.Add(Concat('File: "', fFileName, '" not found'));

  finally
    vExcel.Quit;
    vExcel := Unassigned;

  end;

end;

function TSheetsCompare.CompareSheets: Boolean;
var
  bError: Boolean;

  pCount: Integer;
  iCount: Integer;

  sBuffer: string;

  iResult: Integer;

  sResult: Char;

begin
  Result := False;

  for pCount := 0 to ParamCount - 1 do
    LoadSheetExcel(fSheets[pCount]);

  with fMainList do
    for iCount := 0 to Count - 1 do
      begin
        Result := True;

        sBuffer := Concat('Value: <', Strings[iCount], '>');;
        for pCount := 0 to ParamCount - 1 do
          with fSheets[pCount] do
            begin
              bError := not fList.Find(Strings[iCount], iResult);
              if bError then
                begin
                  sResult := 'Н';
                  Result := False;
                end
              else
                sResult := 'Д';

              sBuffer := Concat(sBuffer, #9, sResult);
            end;

        if not Result then           
          fResultList.Add(sBuffer);
      end;
end;

function TSheetsCompare.ParseParams: Boolean;
var
  pCount: Integer;

begin
  Result := True;

  for pCount := 0 to ParamCount - 1 do
    with fSheets[pCount] do
      begin
        Writeln(Concat('File name:', #9, fFileName));
        Writeln(Concat('Sheet name:', #9, fSheetName));
        Writeln(Concat('Row:', #9, IntToStr(fRow)));
        Writeln(Concat('Col:', #9, IntToStr(fCol)));
        Writeln(Concat('Vector:', #9, cVector[Integer(fVector)]));
        Writeln(Concat('Flag:', #9, fBreakFlag));
      end;

end;

{ Public declarations }

constructor TSheetsCompare.Create;
var
  iCount: Integer;
  sBuffer: string;

begin
  inherited Create;

  SetLength(fSheets, ParamCount);

  for iCount := 1 to ParamCount do
    with fSheets[iCount - 1] do
      begin
        fFileName := ExtractWord(1, ParamStr(iCount), ['#']);
        fSheetName := ExtractWord(2, ParamStr(iCount), ['#']);

        fRow := StrToIntDef(ExtractWord(3, ParamStr(iCount), ['#']), -1);
        fCol := StrToIntDef(ExtractWord(4, ParamStr(iCount), ['#']), -1);

        fVector := vUnd;
        
        sBuffer := ExtractWord(5, ParamStr(iCount), ['#']);
        sBuffer := AnsiUpperCase(sBuffer);

        if sBuffer = 'ROW' then
          fVector := vRow;
        if sBuffer = 'COL' then
          fVector := vCol;
        if sBuffer = 'RNC' then
          fVector := vRnC;

        fBreakFlag := ExtractWord(6, ParamStr(iCount), ['#']);

        fList := TStringList.Create;
        fList.Sorted := True;
      end;

  fMainList := TStringList.Create;
  with fMainList do
    begin
      Sorted := True;
      Duplicates := dupIgnore;
    end;

  fResultList := TStringList.Create;
end;

destructor TSheetsCompare.Destroy;
var
  iCount: Integer;

begin
  with fResultList do
    begin
      SaveToFile('SheetsCompare.log');
      Free;
    end;

  fMainList.Free;

  for iCount := 0 to ParamCount - 1 do
    with fSheets[iCount] do
      fList.Free;

  SetLength(fSheets, 0);

  inherited Destroy;
end;

begin
  CoInitialize(nil);

  if ParamCount > 1 then
    begin
      hSheetsCompare := TSheetsCompare.Create;
      with hSheetsCompare do
        try
          if ParseParams then
            CompareSheets;

        finally
          Free;

        end;
    end
  else
    begin
      Writeln('Error: Params count mismatch');

    end;

  CoUninitialize;
end.



мануал:
+

Программа для сравнения произвольных *.xls файлов. Сравнивает в длинну, ширину и глубину. Альфа.

Параметры запуска:

SheetsCompare.exe C:\SheetsCompare\Data\Journal1.xls#Лист1#2#2#Row# C:\SheetsCompare\Data\Journal2.xls#Лист1#2#3#Col# C:\SheetsCompare\Data\Journal3.xls#Лист1#1#1#RnC#654

C:\SheetsCompare\Data\Journal1.xls# - полный путь к файлу
Лист1# - имя листа (не работает)
2# - строка
2# - столбец
Row# - вектор данных (Row - вниз, Col - вправо, RnC - правониз (диагональ по чухонски),
неопознанный вектор устанавливается в Und(efined) программа возьмет только данные стартовой ячейки)
Конец - флаг остановки (если не указать этот параметр, прога остановится на первой пустой ячейке,
а если указать, но прога его не найдет - вылетит бряк. (щёчик прикрутить штоле...))

Протокол выпадет в *.log файл.

Туду:

Доработать выбор листа: "Лист1" (пока отрабатывает только первый лист), добавить обработку *.odt, отвязатся от excel`я.


Написано на коленке под острой интоксикацией коньяком. Не обессудь.
5 авг 19, 08:57    [21941844]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение 2 файлов (.xlsx) посредством Delphi  [new]
Molchan
Member

Откуда:
Сообщений: 21
x1ca4064,

Получение данных происходит быстро.. Пользователь не будет сам сортировать, выгружаю в Excel и прога должна сразу обработать...
5 авг 19, 09:00    [21941849]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение 2 файлов (.xlsx) посредством Delphi  [new]
Molchan
Member

Откуда:
Сообщений: 21
LocksmithPC,

Спасибо.
5 авг 19, 09:02    [21941850]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение 2 файлов (.xlsx) посредством Delphi  [new]
defecator
Member

Откуда:
Сообщений: 39308
Molchan
Добрый день. Задача такая, имеется 2 Excel файла с расширением .xlsx. Необходимо узнать имеется ли каждая запись первого файла во втором. В каждом файле порядка 8000 строк. Если сравнитьвать посредством OLE получается долго. Куда копать, как быть? Сильно не ругайте, новичок.


Подобную задачу проще решить родными средствами Excel - скриптами
5 авг 19, 09:33    [21941871]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение 2 файлов (.xlsx) посредством Delphi  [new]
ёёёёё
Member

Откуда:
Сообщений: 579
Molchan
Получаю данные с ексель в массив, загружаю в StringGrid. Дальше в счетчиком по строчно проверяю..

"Твою ж мать..." - (с)
5 авг 19, 09:33    [21941872]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение 2 файлов (.xlsx) посредством Delphi  [new]
Molchan
Member

Откуда:
Сообщений: 21
defecator,

Если бы нужно было просто сравнить, то не написал бы в этой ветке..
5 авг 19, 09:59    [21941896]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение 2 файлов (.xlsx) посредством Delphi  [new]
defecator
Member

Откуда:
Сообщений: 39308
Molchan
defecator,

Если бы нужно было просто сравнить, то не написал бы в этой ветке..


написано в первом посте, что
Molchan
имеется 2 Excel файла с расширением .xlsx. Необходимо узнать имеется ли каждая запись первого файла во втором.


и больше ничего иного
5 авг 19, 10:11    [21941902]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение 2 файлов (.xlsx) посредством Delphi  [new]
982183
Member

Откуда: VL
Сообщений: 3052
5 авг 19, 10:51    [21941929]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение 2 файлов (.xlsx) посредством Delphi  [new]
ёёёёё
Member

Откуда:
Сообщений: 579
Molchan,

пробегаешься по первой табличке, берешь текстовое представление каждой строки, помещаешь его в словарь. В качестве ключа используешь строку, в качестве значения - "ничего".

Затем пробегаешься по второй табличке, также берешь текстовое представление каждой строки и проверяешь наличие ее в словаре.
5 авг 19, 11:16    [21941947]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение 2 файлов (.xlsx) посредством Delphi  [new]
Molchan
Member

Откуда:
Сообщений: 21
defecator,

Ветка то Delphi, думаю говорит само за себя.. Долой разговоры:) По делу подсказать сможешь что?
5 авг 19, 11:23    [21941951]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение 2 файлов (.xlsx) посредством Delphi  [new]
ёёёёё
Member

Откуда:
Сообщений: 579
Molchan
...


Какой из предложенных способов ты выбрал?
5 авг 19, 11:29    [21941954]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2 3   вперед  Ctrl      все
Все форумы / Delphi Ответить