Вы не говорите, почему спрашиваете о расчете номера недели в коде RAP.Помимо того, что я не могу найти определение функции AVX
в документации RAP, попытка вычислить номер недели с использованием AVX
в RAP, очевидно, подвержена ошибкам, не является самодокументированием и является практически не подлежащим отладке способом.чтобы сделать это.
Очевидно, ваша функция (? или, может быть, это поле отчета) AVX
возвращает числовое значение, целочисленная часть которого соответствует целочисленной части значения TDateTime.В приведенном ниже примере проекта, который я включил, чтобы показать более простой и менее подверженный ошибкам способ решения проблемы, я включил функцию, которая (я надеюсь) соответствует вашей функции RAP, следующим образом:
function WeekNumber(Day : Integer) : Double;
begin
if (Day >= 42737) and (Day <= 43100) {= Jahr 2017} then begin
result:= (Day - 1 - (42737-1) + 7-((Day -1 - (42737-1) ) mod 7))/7;
end
else begin
if (Day >= 43101) and (Day <= 43465) {= Jahr 2018} then begin
result:= (Day - 1 - (43101-1) + 7-((Day -1 - (43101-1) ) mod 7))/7;
end
else begin
if (Day >= 43466) and (Day <= 43830) {= Jahr 2019} then begin
result:= (Day - 1 - (43466-1) + 7-((Day -1 - (43466-1) ) mod 7))/7;
end
else begin
if (Day >= 43831) and (Day <= 44196) {= Jahr 2020} then begin
result:= (Day - 1 - (43831-1) + 7-((Day -1 - (43831-1) ) mod 7))/7;
end;
end;
end;
end;
end;
(Кстати, при выполнении этого преобразования мне пришлось исправить ряд синтаксических ошибок в вашем RAP-коде, которые вы вскоре найдете, если попытаетесь выполнить преобразование самостоятельно.)
Затем я добавил процедуру впротестируйте эту функцию:
procedure TForm1.TestWeekNumber;
var
Date : TDateTime;
i : integer;
procedure TestInner(Date : TDateTime);
var
WN1,
WN2 : Double;
S,
SError : String;
begin
WN1 := WeekOf(Date);
WN2 := WeekNumber(Trunc(Date));
if WN1 = WN2 then
SError := ''
else
SError := '***';
S := Format('Date: %s WeekOf: %g WeekNumber: %g %s',[ DateTimeToStr(Date), WN1, WN2, SError]);
if SError <> '' then
Memo1.Lines.Add(S);
end;
begin
Date := StrToDateTime('01/01/2017');
Memo1.Lines.BeginUpdate;
try
for i := 0 to 1999 do
TestInner(Date + i);
finally
Memo1.Lines.EndUpdate;
end;
end;
Это сравнивает вашу WeekNumber
со стандартной WeekOf
функцией в DateUtils.Pas, которая возвращает номер недели, как определено стандартом ISO 8601, входного значения TDateTime изаписывает значения в TMemo, когда они дают разные результаты.Ниже приводится выдержка из выходных данных:
Date: 01/01/2017 WeekOf: 52 WeekNumber: 1.13989900694441E-307 ***
Date: 31/12/2018 WeekOf: 1 WeekNumber: 53 ***
Date: 07/01/2019 WeekOf: 2 WeekNumber: 1 ***
Date: 14/01/2019 WeekOf: 3 WeekNumber: 2 ***
Date: 21/01/2019 WeekOf: 4 WeekNumber: 3 ***
Date: 28/01/2019 WeekOf: 5 WeekNumber: 4 ***
Date: 04/02/2019 WeekOf: 6 WeekNumber: 5 ***
Date: 11/02/2019 WeekOf: 7 WeekNumber: 6 ***
[...]
Date: 06/01/2020 WeekOf: 2 WeekNumber: 1 ***
Date: 07/01/2020 WeekOf: 2 WeekNumber: 1 ***
Date: 13/01/2020 WeekOf: 3 WeekNumber: 2 ***
Date: 14/01/2020 WeekOf: 3 WeekNumber: 2 ***
Date: 20/01/2020 WeekOf: 4 WeekNumber: 3 ***
Date: 21/01/2020 WeekOf: 4 WeekNumber: 3 ***
Date: 27/01/2020 WeekOf: 5 WeekNumber: 4 ***
Date: 28/01/2020 WeekOf: 5 WeekNumber: 4 ***
Date: 03/02/2020 WeekOf: 6 WeekNumber: 5 ***
Date: 04/02/2020 WeekOf: 6 WeekNumber: 5 ***
Date: 10/02/2020 WeekOf: 7 WeekNumber: 6 ***
Как вы можете видеть, в конце 2018 года все начинает идти не так, и после этого ошибочные значения, по-видимому, говорят о том, что «выключено одним»ошибки.Я оставляю вас самим исследовать и устранять эту проблему.
Причина, по которой я сам больше не разбираюсь в этом, заключается в том, что мне кажется, что то, как вы это делаете, беспорядочно и сложно избежать.Практически тривиально добавить поддержку номеров недель в отчеты RBuilder, добавив вычисляемое поле со значением номера недели в набор данных, который подает отчет.Код для этого показан ниже.
В качестве альтернативы, вы можете использовать средство ReportBuilder для добавления функции WeekNumber
к языку времени выполнения RAP, которая может принимать любое значение datetime (например, значение из любого поля datetime набора данных)).См., Например, Extending RAP - RAP Pass-Through Functions
в p213 Руководства разработчика ReportBuilder, доступного здесь: Руководство разработчика построителя отчетов .То, что описано, - это, пожалуй, самый гибкий метод отображения функции Delphi в отчете, хотя в ISTR есть и другие.
Код (за исключением компонентов RBuilder для простоты)
type
TForm1 = class(TForm)
CDS1: TClientDataSet;
DataSource1: TDataSource;
DBGrid1: TDBGrid;
DBNavigator1: TDBNavigator;
procedure FormCreate(Sender: TObject);
procedure CDS1CalcFields(DataSet: TDataSet);
private
procedure CreateDataSetFields;
protected
public
end;
[...]
implementation
uses
DateUtils;
procedure TForm1.FormCreate(Sender: TObject);
var
i : Integer;
begin
CreateDataSetFields; // see below
CDS1.CreateDataSet;
// Insert one row per day for current year
for i := 1 to 365 do begin
CDS1.InsertRecord([i, i + Now - DayOfTheYear(Now)]);
end;
CDS1.First;
end;
procedure TForm1.CDS1CalcFields(DataSet: TDataSet);
begin
// This sets the WeekNo calculated field to the value returned by the DateUtils.WeekOf function
DataSet.FieldByName('WeekNo').AsInteger := WeekOf(DataSet.FieldByName('Date').AsDateTime);
end;
procedure TForm1.CreateDataSetFields;
var
Field : TField;
begin
Field := TIntegerField.Create(Self);
Field.FieldKind := fkData;
Field.FieldName := 'ID';
Field.Name := 'ID';
Field.DataSet := CDS1;
Field := TDateTimeField.Create(Self);
Field.FieldKind := fkData;
Field.FieldName := 'Date';
Field.Name := 'Date';
Field.DataSet := CDS1;
Field := TIntegerField.Create(Self);
Field.FieldKind := fkInternalCalc;
Field.FieldName := 'WeekNo';
Field.Name := 'WeekNo';
Field.DataSet := CDS1;
end;