Найти тему
Laderuna

Приложение для обработки файла Excel на Delphi 7

Добрый день уважаемые читатели!

Задача.

Имеется файл .xls, в котором несколько столбцов с названиями: дата, наименование рецепта, название компонента, с названием компонентов столбцов несколько. В столбце с наименованием рецепта беспорядочно записаны строки, в которых непосредственно содержатся наименования рецептов. Рецептов около десяти штук. Некоторые строки пустые. В соседних столбцах с названием компонентов, в ячейках, содержатся значения их массы. Один рецепт делается в несколько подходов, поэтому имеется столбец с названием "Цикл". Циклов-подходов на изготовление одного рецепта всегда бывает разное количество, иногда один цикл, иногда 6, иногда 57, поэтому и строк бывает разное количество. Требуется посчитать сумму массы компонентов по каждому рецепту. Записать макрос в данном случае не решит задачу, потому что каждый день количество циклов разное, соответственно и количество строк меняется, макрос же будет суммировать конкретные адреса ячеек. К тому же, создать макрос не даст тот факт, что название рецепта будет записано каждый раз в новую строку, потому что количество циклов неизвестно заранее...

Решение.

Для начала откроем файл:

uses

ComObj // это чтобы Excel открылся

procedure ButtonClick(Sender: TObject);

var

Excel: Variant;

j, k: integer;

s, s1, s2, s3, z: string;

const xlCellTypeLast=$000000B;

begin

Excel :=CreateoleObject('Excel.Application');

Excel.DisplayAlerts := false;

OpenDialog1.Filter:=' File MS Excel|*.xls;*.xlsx|';

if not OpenDialog.Execute then Exit;

Excel.Workbooks.Open(OpenDialog.FileName, False);

Прочитаем все строки в переменные:

j :=excel.ActiveCell.SpecialCells(xlCellTypeLast).Row;

k :=1;

while k<>j+1 do

begin

Запишем по столбцам:

s :=excel.cells[k, 1].value; // в первом столбце содержится дата

s1 :=excel.cells[k, 4].value;//в этом столбце наименование рецепта

s2 :=excel.cells[k, 6].value;//здесь масса первого компонента

s3 :=excel.cells[k, 7].value;//здесь масса второго компонента (остальные компоненты здесь не пишу, т.к. там просто меняется номер столбца)

z :=excel.cells[k, 3].value;//в третьем столбце строки с типами масс, нас интересует строка "Вес фактический"

inc(k);

if (z = 'Вес фактический') and (Pos(Combobox.Text, s1)<>0) //собираем только строки с фактическим весом, а в комбо-боксе запишем наименования наших рецептов (около 10 штук) и соберём их также

Поместим все, что собрали в StringGrid:

then begin

StringGrid.RowCount:=StringGrid.RowCount+1;

Stringgrid.cells[1,StringGrid.RowCount-1]:=s;

Stringgrid.cells[2,StringGrid.RowCount-1]:=s1;

Stringgrid.cells[3,StringGrid.RowCount-1]:=s2;

Stringgrid.cells[4,StringGrid.RowCount-1]:=s3;

и т.д.

Если в ячейке с массой пусто, проставим в неё ноль (это для выполнения суммирования в дальнейшем):

if Trim(StringGrid.Cells[3, StringGrid.RowCount-1])= '' then StringGrid.Cells[3, StringGrid.RowCount-1] := '0';

end;

Завершаем:

Excel.Workbooks.Close;

Excel.Quit;

Excel :=unassigned;

Это для пользователя программы полоса загрузки, чтобы не принял процесс зависшим:

ProgressBar.Position:=ProgressBar.Max;

В конце уведомление:

ShowMessage('Загрузка завершена!');

ProgressBar1.Position:= 0;

end;

Это если пожелаете кнопку очистки всех ячеек StringGrid: StringGrid.RowCount := 1;

Итак, мы получили все строки с искомым рецептом по фактическому весу, но теперь нам требуется суммировать значения масс всех циклов приготовления.

Для этого суммируем ячейки по каждому компоненту, удаляя повторяющиеся строки из столбца с названием рецепта:

procedure TForm.ButtonClick(Sender: TObject);

var

SumA, SumB, SumC, Sum1, Sum2, Sum3 : Real;

x, y : Integer;

begin

Пройдем двумя циклами:

for x:=1 to StringGrid.RowCount - 1 do

begin

for y:=x+1 to StringGrid.RowCount - 1 do

begin

if (StringGrid.Cells[2,x]) = (StringGrid.Cells[2,y]) then

begin //Если строки имеют одинаковое название, то :

Сохраним значение ячейки из столбца с компонентом в переменной:

Sum := 0;

Sum:= Sum+StrToFloat(StringGrid.Cells[3,x]);

//Проделаем для всех столбцов с компонентами.

Удаляем одинаковые строки в столбце с наименованием рецептов:

for z:= x to StringGrid.RowCount-2 do

StringGrid.Rows[z]:= StringGrid.Rows[z+1];

StringGrid.RowCount:= StringGrid.RowCount-1;

Прибавим сохраненное значение в оставшуюся после удаления строку:

Sum1 := 0;

Sum1:= Sum1+StrToFloat(StringGrid.Cells[3,x]);

StringGrid.Cells[3,x]:= FloatToStr(Sum+Sum1);

//Проделаем для всех столбцов с компонентами.

end;

Теперь нам надо сохранить посчитанное обратно в Excel :

procedure ButtonClick(Sender: TObject);

var

Excel, WorkBook, Sheet:variant;

i, j: integer;

FName: string;

begin

if SaveDialog.Execute then

FName := SaveDialog.FileName

else

Exit;

Excel:=CreateOleObject('Excel.Application');

Excel.DisplayAlerts:=False;

Excel.Visible:= False;

Workbook:=Excel.

Workbooks.Add;

Workbook.SaveAs(FName);

Sheet:= Workbook.ActiveSheet;

for i:= 0 to StringGrid.RowCount - 1 do

begin

for j:= 0 to StringGrid.ColCount - 1 do

Sheet.Cells[i+1, j+1]:= StringGrid1.Cells[j, i];

end;

Workbook.Save;

Workbook.Close;

Excel.Quit;

Excel:= UnAssigned;

MessageBox(Handle,'Экспорт данных завершен','Внимание!',0);

end;

Спасибо за прочтение, жду комментарии, вопросы и предложения. Подписывайтесь на мой канал, если пожелаете!

Наука
7 млн интересуются