powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Табель посещения
13 сообщений из 13, страница 1 из 1
Табель посещения
    #39914660
Kadekin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день.
Возник вопрос в реализации Табеля посещения.
Есть база данных в нее вносятся люди и дата их прихода. (Люди очень часто меняются)
В просторах интернета я видел, что люди реализовывают на StringGride. Но по специфике этот элемент не подходит.
Также я видел что есть реализация на DBGridEh - но не описано как они это реализовали
https://www.sql.ru/forum/1177605/dbgrideh-v-kachestve-tabelya-ucheta-rabochego-vremeni
Подскажите как правильно реализовать.
...
Рейтинг: 0 / 0
Табель посещения
    #39914664
DimaBr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не важно StringGrid или DBGrid или DBGridEh. Их цель всего лишь отобразить имеющиеся данные
...
Рейтинг: 0 / 0
Табель посещения
    #39914668
zinpub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
cxScheduler
...
Рейтинг: 0 / 0
Табель посещения
    #39914688
DimaBr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kadekin
Подскажите как правильно реализовать.

Делай так, как написано в тех задании.
...
Рейтинг: 0 / 0
Табель посещения
    #39914970
Kadekin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
DimaBr,
вопрос в том, что столбец с ФИО я могу создать, а как создать с датами и в запросе вывести в эти столбцы значения.
Я этого не могу понять.
...
Рейтинг: 0 / 0
Табель посещения
    #39915095
DimaBr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Нужно создать таблицы:
таблицытаблица табелей
Код: sql
1.
2.
3.
4.
IdTableWork int identity(1,1) -- ID Табеля
NameTableWork varchar(100) -- наименование табеля
IdStructure int -- подразделение
ADate smalldatetime -- месяц и год


таблица сотрудников в табеле
Код: sql
1.
2.
3.
4.
5.
6.
IdTableWorkEmployee int identity(1,1) -- ID
IdTableWork int, -- ID табеля
IdEmployee int -- ID сотрудника
IdPost int -- ID должности
Salary money -- оклад
-- и прочие атрибуты сотрудника в табеле


таблица дней табеля
Код: sql
1.
2.
3.
4.
5.
6.
7.
IdTableWorkDay int identity(1,1) -- ID
IdTableWork int - ID табеля
IdEmployee int, -- ID сотрудника
DateDay smalldatetime, -- число
IdTypeDay int, -- тип дня (явка, вечерний, ночной, больничный, отпуск и т.д) -
QuantityHour money, -- количество часов
IndexDay int -- по хорошему одного типа дня мало. Человек в один день может работать и в дневную смену и в вечернюю



Далее реализуем интерфейс.
Календарик для выбора месяца/года
Список табелей, который заполняется в зависимости от выбранной даты
Сотрудники табеля (список людей и их характеристиками для выбранного табеля)
Сам табель для выбранного сотрудника
...
Рейтинг: 0 / 0
Табель посещения
    #39915180
istrebitel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Я реализовывал на DBGridEh и MemoryTable.
В TMemTableEh Завёл поля с Id Подразделений и Работников, 31 поле по дням недели. Там ещё 31 Byte поле под флаги для быстрой фильтрации. Данные получаются запросом с сортировкой Подразделение, Работник, Дата в fdqCtrlData. При каждом изменении пары Подразделение, Работник в таблице создаётся строка.

Заполнение таблицы
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
procedure Tfrm1CTimeSheet.CtrlFillMemoryTable;
var
  oldPodr, oldWorker, DataFieldIndex, TrigFieldIndex, ColumnIndex, i, lastDayInMonth :Integer;
  dw : DayMonday..DaySunday;
  dt :TDate;
  DataField :TField;
  TrigField :TByteField;
  TitlColor, ColumnColor :TColor;
  DayFlags, MonthFlags :TCtrlFlags;
  s :string;
  function CtrlGroupChanged :Boolean;
  begin
    Result := (oldPodr <> fdqCtrlDatapr_podr_id.Value) or (oldWorker <> fdqCtrlDatapr_worker_id.Value);
  end;
begin
  mtCtrlCross.EmptyTable; // <- MemoryTable отображаемый в гриде
  mtCtrlCross.Close;
  mtCtrlCross.AfterScroll := nil;
  mtCtrlCross.TreeList.Active := False;
  mtCtrlCross.Filter := '';
  mtCtrlCross.Filtered := False;
  mtCtrlCross.Open;
  mtCtrlCross.DisableControls;
  try
    if not fdqCtrlData.IsEmpty then
    begin
      oldPodr := fdqCtrlDatapr_podr_id.Value;
      oldWorker := fdqCtrlDatapr_worker_id.Value;
      mtCtrlCross.Append;
      
      mtCtrlCrossWorker.Value := fdqCtrlDatapr_worker_id.Value;
      mtCtrlCrossPodr.Value := fdqCtrlDatapr_podr_id.Value;
      mtCtrlCrossPodr4TreeId.AsVariant := Null;
      mtCtrlCrossPodr4TreeAncestor.Value := fdqCtrlDatapr_podr_id.Value;
      DataFieldIndex := DayOf(fdqCtrlDatapr_date.AsDateTime) + 3; // Определяем в какую колонку записывать данные
      DataField := mtCtrlCross.Fields[DataFieldIndex];
      
      if not fdqCtrlDataplan_id.IsNull then
      begin
        if (fdqCtrlDataplan_pr_absence.Value = 'Я') and (fdqCtrlDatapr_graveyard.Value = 1) then // Ночная смена
          DataField.AsString := fdqCtrlDataplan_pr_absence.Value + '(Н)'
        else
          DataField.AsString := fdqCtrlDataplan_pr_absence.Value;
      end;
      fdqCtrlData.Next;

      while not fdqCtrlData.Eof do
      begin
        if CtrlGroupChanged then
        begin
          mtCtrlCross.Post;
          mtCtrlCross.Append;
          oldPodr := fdqCtrlDatapr_podr_id.Value;
          oldWorker := fdqCtrlDatapr_worker_id.Value;
        end;
        mtCtrlCrossWorker.Value := fdqCtrlDatapr_worker_id.Value;
        mtCtrlCrossPodr.Value := fdqCtrlDatapr_podr_id.Value;
        mtCtrlCrossPodr4TreeId.AsVariant := Null;
        mtCtrlCrossPodr4TreeAncestor.Value := fdqCtrlDatapr_podr_id.Value;
        DataFieldIndex := DayOf(fdqCtrlDatapr_date.AsDateTime) + 3;
        DataField := mtCtrlCross.Fields[DataFieldIndex];
        if not fdqCtrlDataplan_id.IsNull then
        begin
          if (fdqCtrlDataplan_pr_absence.Value = 'Я') and (fdqCtrlDatapr_graveyard.Value = 1) then
            DataField.AsString := fdqCtrlDataplan_pr_absence.Value + '(Н)'
          else
            DataField.AsString := fdqCtrlDataplan_pr_absence.Value;
        end;
        fdqCtrlData.Next;
      end;
      if mtCtrlCross.State in [dsInsert, dsEdit] then mtCtrlCross.Post;
    end;
    // Добавляем строки подразделений
    dm3.fdq.Open;
    while not dm3.fdq.Eof do
    begin
      mtCtrlCross.Append;
      mtCtrlCrossPodr4TreeId.Value := dm3.fdq.Fields[0].Value;
      mtCtrlCrossPodr.Value := dm3.fdq.Fields[0].Value;
      mtCtrlCrossPodr4TreeAncestor.Value := dm3.fdq.Fields[1].Value;
      dm3.fdq.Next;
    end;
    dm3.fdq.Close;
    if mtCtrlCross.State in [dsInsert, dsEdit] then mtCtrlCross.Post;
    mtCtrlCross.First;
    mtCtrlCross.TreeList.Active := True;
    // Оформление заголовка
	lastDayInMonth := System.DateUtils.DaysInMonth(dteCtrlStart.Value);
    for i := 1 to lastDayInMonth do
    begin
      DataFieldIndex := i + 3;
      ColumnIndex := i + 1;
      dt := RecodeDay(dteCtrlStart.Value, i);
      dw := DayOfTheWeek(dt);
      TitlColor := clWindowText;
      ColumnColor := clWindow;
      case dw of
        DayMonday : s := 'пн';
        DayTuesday : s := 'вт';
        DayWednesday : s := 'ср';
        DayThursday : s := 'чт';
        DayFriday : s := 'пт';
        DaySaturday :
          begin
            s := 'сб';
            TitlColor := clRed;
            ColumnColor := gclLightYellow;
          end;
        DaySunday :
          begin
            s := 'вс';
            TitlColor := clRed;
            ColumnColor := gclLightYellow;
          end;
      end;
      mtCtrlCross.Fields[DataFieldIndex].DisplayLabel := IntToStr(i) + sLineBreak + s;
      //dbgCtrl.Columns[ColumnIndex].Title.Caption := IntToStr(i) + #13 + s;
      dbgCtrl.Columns[ColumnIndex].Title.Font.Color := TitlColor;
      dbgCtrl.Columns[ColumnIndex].Color := ColumnColor;
      dbgCtrl.Columns[ColumnIndex].Visible := True;
      dbgCtrl.Columns[ColumnIndex].DynProps[cstdvDateColumn].AsDateTime := dt;
    end;
    for i := lastDayInMonth + 1 to 31 do
    begin
      ColumnIndex := i + 1;
      dbgCtrl.Columns[ColumnIndex].Visible := False;
    end;
  finally
    mtCtrlCross.EnableControls;
  end;
  SetCtrlDataFilter;
  mtCtrlCross.AfterScroll := mtCtrlCrossAfterScrollEv;
  dbgCtrlCellSelectionChanged;
end;

...
Рейтинг: 0 / 0
Табель посещения
    #39915183
DimaBr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
istrebitel
Я реализовывал на DBGridEh и MemoryTable.

А сколько часов отработал человек в определённый день ?
А как у вас зафиксировать что человек работал 4часа в дневную смену 2,5 в вечернюю и 1,5 в ночную ?
...
Рейтинг: 0 / 0
Табель посещения
    #39916187
istrebitel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В этом интерфейсе не просили часы отображать. Ночные смены отображаются как Я(Н).
Поля в MemoryTable объявлены как TStringField так что ничего не мешает написать
DataField.AsString := 'Я' + ' ' + время общее + sLineBreak +'ВЧ' + ' ' + время вечернее + sLineBreak +'Н' + ' ' + время ночное;
В БД табель хранится в таблице со структурой
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
CREATE TABLE [dbo].[tablename](
	[tmsh_id] [bigint] IDENTITY(1,1) NOT NULL,
	[tmsh_date] [datetime] NOT NULL,
	[tmsh_worker_id] [int] NOT NULL,
	[tmsh_post_id] [int] NULL,
	[tmsh_workplan_id] [int] NULL,
	[tmsh_t1] [nvarchar](2) NOT NULL,
	[tmsh_v1] [numeric](4, 2) NULL,
	[tmsh_t2] [nvarchar](2) NULL,
	[tmsh_v2] [numeric](4, 2) NULL,
	[tmsh_t3] [nvarchar](2) NULL,
	[tmsh_v3] [numeric](4, 2) NULL,
	[tmsh_podr_id] [int] NULL,
	[tmsh_dept_id] [nvarchar](15) NULL,
	[tmsh_mantab_id] [nvarchar](6) NULL
)



Для вашего случая будет
tmsh_t1 = 'Я'
tmsh_v1 = 8 (Общее время)
tmsh_t2 = 'ВЧ'
tmsh_v2 = 2,5
tmsh_t3 = 'Н'
tmsh_v3 = 1,5
...
Рейтинг: 0 / 0
Табель посещения
    #39916194
DimaBr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
istrebitel

Код: sql
1.
2.
3.
4.
CREATE TABLE [dbo].[tablename](
	[tmsh_t3] [nvarchar](2) NULL,
	[tmsh_v3] [numeric](4, 2) NULL,
)



Вы уверенны что ТРЁХ признаков достаточно ? А если человек взял отгул на пол дня (отпуск за свой счёт), а остальное время отработал Я+В+Н ?
...
Рейтинг: 0 / 0
Табель посещения
    #39916195
istrebitel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ну когда я спрашивал у ОТиЗа мне сказали 3-х достаточно. Это не система ведения табеля, он ведётся в 1С. Это система контроля работы предприятия. Из 1С загружается план. Из СКУДа загружаются проходы. Мастера каждый день табелируют работников своих подразделений в системе. ОТиЗ контролирует расхождения 1С с фактом отмеченным в системе (запоздание ввода приказов о смене графика например), если не устраняют вовремя получают пистон от Генерального.
...
Рейтинг: 0 / 0
Табель посещения
    #39916220
энди
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Никогда не мог понять почему время при показе datetime обычно показывают вплоть до секунд
Формула-1 не иначе :))
...
Рейтинг: 0 / 0
Табель посещения
    #39916225
istrebitel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Да просто никто не заморачивается DisplayFormat. Ведь надо чтоб было готово уже вчера.
...
Рейтинг: 0 / 0
13 сообщений из 13, страница 1 из 1
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Табель посещения
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]