Если все подзадачи выполнены или сняты с контроля (т.е. ни одна из них не имеет статус "НА КОНТРОЛЕ") - задача снята с контроля.
Если хотя бы одна из подзадач имеет статус "НА КОНТРОЛЕ", значит и задача должна иметь такой статус.
Если в задаче нет подзадач, то её статус определяется на форме frmTask (сейчас для этого имеется поле task.status и CheckStatus)

DriveSoft wrote:

Повторюсь, если у вас состояние задачи определяется только состояниями подзадачи, то поле task.status вам просто не нужно.

Состояние задачи определяется не только состоянием подзадач. В задаче может не быть ни одной подзадачи, в этом случае нужно поле task.status и, соответственно, CheckStatus на форме frmTask.

DriveSoft wrote:

1. Потому что у вас может измениться этот статус автоматически только в событии формы

procedure frmTask_OnShow (Sender: string; Action: string); 

if frmTask.CheckStatusYes.Checked = True then frmTask.CheckStatus.Checked := True else frmTask.CheckStatus.Checked := False;

Именно так у меня и записано в строке 48.
Когда меняешь статус субзадачи на "НА КОНТРОЛЕ" изменяется статус задачи на главной форме. Когда же статус всех субзадач меняешь на "ВЫПОЛНЕНО" изменения на главной форме не происходит, а должно на главной форме в статусе задачи записаться "ВЫПОЛНЕНО".

1) В приложенном проекте редактированием второй задачи измените статус первой субзадачи на "ВЫПОЛНЕНО". ПРОБЛЕМА: на главной форме статус второй задачи всё равно останется "НА КОНТРОЛЕ". Для того, чтобы он изменился на "ВЫПОЛНЕНО" нужно ещё раз редактированием сохранить запись. Пол дня бьюсь над этим - и всё никак. Прошу помочь.
2) Всплывающая подсказка обязательных полей. Как изменить текст?

105

(12 replies, posted in Russian)

DriveSoft wrote:

Сделал тестовое приложение.

А ещё звук в процедуру Form1_Button1_OnAfterClick:

 MessageBeep(1); //Звуковой сигнал 

СПАСИБО!!!!!!!!!!

Тот же скрипт для украиноязычных проектов:

{
перевод на язык паскаля для Фаст Репорта
Наумов Денис
ICQ 368-254-335
mailTo denis-naymov1985@mail.ru
for my web NetSoftWare.Ucoz.ru
основна
http://delphiworld.narod.ru/base/sum_written_out7.html
  
{Пропись © Близнец Антон '99 http:\\anton-bl.chat.ru\delphi\1001.htm }
{ 1000011.01->'Один миллион одинадцать рублей 01 копейка'      
}

const
  Max000 = 6; {Кол-во триплетов - 000}
  MaxPosition = Max000 * 3; {Кол-во знаков в числе }
  var

    c100: array[0..9] of string;
    c11: array[0..9] of string;
    c10: array[0..9] of string;
    c1: array[0..1, 0..9] of string;
    c1000w: array[0..Max000] of integer;
    c1000:array[0..Max000] of string;
    w:array[0..1, 0..9] of string;
    ruble: array[0..9] of string;
    Kopeek: array[0..9] of string;


procedure initalize;
begin
       c1000[0]:='';
       c1000[1]:='тисяч';
       c1000[2]:='мільйон';
       c1000[3]:='мільярд';
       c1000[4]:='трильйон';
       c1000[5]:='квадралліон';
       c1000[6]:='квінтильйон';

       c1000w[0]:=0;
       c1000w[1]:=1;
       c1000w[2]:=0;
       c1000w[3]:=0;
       c1000w[4]:=0;
       c1000w[5]:=0;
       c1000w[6]:=0;

       w[0,0]:='ів ';
       w[0,1]:=' ';
       w[0,2]:='а ';
       w[0,3]:='а ';
       w[0,4]:='а ';
       w[0,5]:='ів ';
       w[0,6]:='ів ';
       w[0,7]:='ів ';
       w[0,8]:='ів ';
       w[0,9]:='ів ';
       w[1,0]:=' ';
       w[1,1]:='а ';
       w[1,2]:='і ';
       w[1,3]:='і ';
       w[1,4]:='і ';
       w[1,5]:=' ';
       w[1,6]:=' ';
       w[1,7]:=' ';
       w[1,8]:=' ';
       w[1,9]:=' ';
     c100[0]:='';
     c100[1]:='сто ';
     c100[2]:='двісті ';
     c100[3]:='триста ';
     c100[4]:='чотириста ';
     c100[5]:='п’ятсот ';
     c100[6]:='шістсот ';
     c100[7]:='сімсот ';
     c100[8]:='вісімсот ';
     c100[9]:='дев’ятсот ';

      c10[0]:='';
      c10[1]:='десять ';
      c10[2]:='двадцять ';
      c10[3]:='тридцять ';
      c10[4]:='сорок ';
      c10[5]:='п’ятдесят ';
      c10[6]:='шістдесят ';
      c10[7]:='сімдесят ';
      c10[8]:='вісімдесят ';
      c10[9]:='дев’яносто ';

      c11[0]:='';
      c11[1]:='один';
      c11[2]:='дві';
      c11[3]:='три';
      c11[4]:='чотир';
      c11[5]:='п’ят';
      c11[6]:='шіст';
      c11[7]:='сім';
      c11[8]:='вісім';
      c11[9]:='дев’ят';


      c1[0,0]:='';
      c1[0,1]:='один ';
      c1[0,2]:='два ';
      c1[0,3]:='три ';
      c1[0,4]:='чотири ';
      c1[0,5]:='п’ять ';
      c1[0,6]:='шість ';
      c1[0,7]:='сім ';
      c1[0,8]:='вісім ';
      c1[0,9]:='дев’ять ';

      c1[1,0]:='';
      c1[1,1]:='одна ';
      c1[1,2]:='дві ';
      c1[1,3]:='три ';
      c1[1,4]:='чотири ';
      c1[1,5]:='п’ять ';
      c1[1,6]:='шість ';
      c1[1,7]:='сім ';
      c1[1,8]:='вісім ';
      c1[1,9]:='дев’ять ';

      ruble[0]:='ень';
      ruble[1]:='ня';
      ruble[2]:='ні';
      ruble[3]:='ень';
      ruble[4]:='ні';
      ruble[5]:='ень';
      ruble[6]:='ень';
      ruble[7]:='ень';
      ruble[8]:='ень';
      ruble[9]:='ень';

      Kopeek[0]:='ок';
      Kopeek[1]:='ка';
      Kopeek[2]:='ки';
      Kopeek[3]:='ки';
      Kopeek[4]:='ки';
      Kopeek[5]:='ок';
      Kopeek[6]:='ок';
      Kopeek[7]:='ок';
      Kopeek[8]:='ок';
      Kopeek[9]:='ок';




end;

function Ceil(const X: Extended): Integer;
begin
  Result:=(Trunc(X));
  if Frac(X) > 0 then
    Inc(Result);
end;

Function IIF2( bln:boolean; TruePart:string; FalsePart:string):string;
begin
  if bln then
    Result := TruePart
  else
    Result := FalsePart;

end;

  function Num000toStr(S: string; woman: integer): string;
    {Num000toStr возвращает число для триплета}

  begin {Num000toStr}
    Result:= c100[ord(s[1])-ord('0')] + iif2((s[2] = '1') and (s[3] > '0'), c11[ord(s[3])-ord('0')] +
      'надцать ', c10[ord(s[2])-ord('0')] + c1[woman, ord(s[3])-ord('0')]);
  end; {Num000toStr}

function NumToStr(s: string): string; {Возвращает число прописью}
var
  s000: string;

  isMinus: Boolean;
  isw:integer;
  i: integer; //Сч?тчик триплетов
begin

  Result := '';
  i := 0;
   isMinus := (s <> '') and (s[1] = '-');

  if isMinus then
    s := Copy(s, 2, Length(s) - 1);
  while not ((i >= Ceil(Length(s) / 3)) or (i >= Max000)) do
  begin
    s000 := Copy('00' + s, Length(s) - i * 3, 3);
    isw := c1000w[i];
    if (i > 0) and (s000 <> '000') then //тысячи и т.д.
      Result := c1000[i] + w[Isw, strtoint(iif2(s000[2] = '1', '0', s000[3]))] + Result;
    Result := Num000toStr(s000, isw) + Result;
    Inc(i)
  end;
  if Result = '' then
    Result := 'ноль';
  if isMinus then
    Result := 'минус ' + Result;
end; {NumToStr}

function TrimLeft(const S: string): string;
var
  I, L: Integer;
begin
  L := Length(S);
  I := 1;
  while (I <= L) and (S[i] <= ' ') do Inc(I);
  Result := Copy(S, I, 32565555);
end;

function RealToRouble(c: Extended): string;


  function ending(const s: string): Char;
  var
    l: Integer; //С l на 8 байт коротче $50->$48->$3F
  begin //Возвращает индекс окончания

    l := Length(s);
     if(l > 1) and (s[l-1]='1') then
     result:='0'
    else
    result:=s[l];

  end;

var
  rub: string;
  kop: string;
  h,x:integer;
begin {Возвращает число прописью с рублями и копейками}

  Result:=formatfloat('0.00',c);
  h:=length(Result);
  for X:=h to 18 do Result:=' '+Result;
  //Str(c: MaxPosition + 3: 2, Result);

  if Pos('E', Result) = 0 then //Если число можно представить в строке <>1E+99
  begin
    rub := TrimLeft(Copy(Result, 1, Length(Result) - 3));
    kop := Copy(Result, Length(Result) - 1, 2);
    Result := NumToStr(rub) + ' грив'+ruble[strtoint(ending(rub))]
      + ' ' + kop + ' копій' + Kopeek[strtoint(ending(kop))];
    Result := UpperCase(Result[1]) + Copy(Result, 2, Length(Result) - 1);

  end;
end;
function GetSummaToText(r:real):string;
begin
initalize;
result:=RealToRouble(r);
end;
  
begin
   memo1.lines.text:=GetSummaToText(125159256458359.44);
end.

Нашёл в интернете такой скрипт:

{
перевод на язык паскаля для Фаст Репорта
Наумов Денис
ICQ 368-254-335
mailTo denis-naymov1985@mail.ru
for my web NetSoftWare.Ucoz.ru
основна
http://delphiworld.narod.ru/base/sum_written_out7.html
  
{Пропись © Близнец Антон '99 http:\\anton-bl.chat.ru\delphi\1001.htm }
{ 1000011.01->'Один миллион одинадцать рублей 01 копейка'      
}

const
  Max000 = 6; {Кол-во триплетов - 000}
  MaxPosition = Max000 * 3; {Кол-во знаков в числе }
  var

    c100: array[0..9] of string;
    c11: array[0..9] of string;
    c10: array[0..9] of string;
    c1: array[0..1, 0..9] of string;
    c1000w: array[0..Max000] of integer;
    c1000:array[0..Max000] of string;
    w:array[0..1, 0..9] of string;
    ruble: array[0..9] of string;
    Kopeek: array[0..9] of string;


procedure initalize;
begin
       c1000[0]:='';
       c1000[1]:='тысяч';
       c1000[2]:='миллион';
       c1000[3]:='миллиард';
       c1000[4]:='триллион';
       c1000[5]:='квадраллион';
       c1000[6]:='квинтиллион';

       c1000w[0]:=0;
       c1000w[1]:=1;
       c1000w[2]:=0;
       c1000w[3]:=0;
       c1000w[4]:=0;
       c1000w[5]:=0;
       c1000w[6]:=0;

       w[0,0]:='ов ';
       w[0,1]:=' ';
       w[0,2]:='а ';
       w[0,3]:='а ';
       w[0,4]:='а ';
       w[0,5]:='ов ';
       w[0,6]:='ов ';
       w[0,7]:='ов ';
       w[0,8]:='ов ';
       w[0,9]:='ов ';
       w[1,0]:=' ';
       w[1,1]:='а ';
       w[1,2]:='и ';
       w[1,3]:='и ';
       w[1,4]:='и ';
       w[1,5]:=' ';
       w[1,6]:=' ';
       w[1,7]:=' ';
       w[1,8]:=' ';
       w[1,9]:=' ';
     c100[0]:='';
     c100[1]:='сто ';
     c100[2]:='двести ';
     c100[3]:='триста ';
     c100[4]:='четыреста ';
     c100[5]:='пятьсот ';
     c100[6]:='шестьсот ';
     c100[7]:='семьсот ';
     c100[8]:='восемьсот ';
     c100[9]:='девятьсот ';

      c10[0]:='';
      c10[1]:='десять ';
      c10[2]:='двадцать ';
      c10[3]:='тридцать ';
      c10[4]:='сорок ';
      c10[5]:='пятьдесят ';
      c10[6]:='шестьдесят ';
      c10[7]:='семьдесят ';
      c10[8]:='восемьдесят ';
      c10[9]:='девяносто ';

      c11[0]:='';
      c11[1]:='один';
      c11[2]:='две';
      c11[3]:='три';
      c11[4]:='четыр';
      c11[5]:='пят';
      c11[6]:='шест';
      c11[7]:='сем';
      c11[8]:='восем';
      c11[9]:='девят';


      c1[0,0]:='';
      c1[0,1]:='один ';
      c1[0,2]:='два ';
      c1[0,3]:='три ';
      c1[0,4]:='четыре ';
      c1[0,5]:='пять ';
      c1[0,6]:='шесть ';
      c1[0,7]:='семь ';
      c1[0,8]:='восемь ';
      c1[0,9]:='девять ';

      c1[1,0]:='';
      c1[1,1]:='одна ';
      c1[1,2]:='две ';
      c1[1,3]:='три ';
      c1[1,4]:='четыре ';
      c1[1,5]:='пять ';
      c1[1,6]:='шесть ';
      c1[1,7]:='семь ';
      c1[1,8]:='восемь ';
      c1[1,9]:='девять ';

      ruble[0]:='ей';
      ruble[1]:='ь';
      ruble[2]:='я';
      ruble[3]:='я';
      ruble[4]:='я';
      ruble[5]:='ей';
      ruble[6]:='ей';
      ruble[7]:='ей';
      ruble[8]:='ей';
      ruble[9]:='ей';

      Kopeek[0]:='ек';
      Kopeek[1]:='йка';
      Kopeek[2]:='йки';
      Kopeek[3]:='йки';
      Kopeek[4]:='йки';
      Kopeek[5]:='ек';
      Kopeek[6]:='ек';
      Kopeek[7]:='ек';
      Kopeek[8]:='ек';
      Kopeek[9]:='ек';




end;

function Ceil(const X: Extended): Integer;
begin
  Result:=(Trunc(X));
  if Frac(X) > 0 then
    Inc(Result);
end;

Function IIF2( bln:boolean; TruePart:string; FalsePart:string):string;
begin
  if bln then
    Result := TruePart
  else
    Result := FalsePart;

end;

  function Num000toStr(S: string; woman: integer): string;
    {Num000toStr возвращает число для триплета}

  begin {Num000toStr}
    Result:= c100[ord(s[1])-ord('0')] + iif2((s[2] = '1') and (s[3] > '0'), c11[ord(s[3])-ord('0')] +
      'надцать ', c10[ord(s[2])-ord('0')] + c1[woman, ord(s[3])-ord('0')]);
  end; {Num000toStr}

function NumToStr(s: string): string; {Возвращает число прописью}
var
  s000: string;

  isMinus: Boolean;
  isw:integer;
  i: integer; //Сч?тчик триплетов
begin

  Result := '';
  i := 0;
   isMinus := (s <> '') and (s[1] = '-');

  if isMinus then
    s := Copy(s, 2, Length(s) - 1);
  while not ((i >= Ceil(Length(s) / 3)) or (i >= Max000)) do
  begin
    s000 := Copy('00' + s, Length(s) - i * 3, 3);
    isw := c1000w[i];
    if (i > 0) and (s000 <> '000') then //тысячи и т.д.
      Result := c1000[i] + w[Isw, strtoint(iif2(s000[2] = '1', '0', s000[3]))] + Result;
    Result := Num000toStr(s000, isw) + Result;
    Inc(i)
  end;
  if Result = '' then
    Result := 'ноль';
  if isMinus then
    Result := 'минус ' + Result;
end; {NumToStr}

function TrimLeft(const S: string): string;
var
  I, L: Integer;
begin
  L := Length(S);
  I := 1;
  while (I <= L) and (S[i] <= ' ') do Inc(I);
  Result := Copy(S, I, 32565555);
end;

function RealToRouble(c: Extended): string;


  function ending(const s: string): Char;
  var
    l: Integer; //С l на 8 байт коротче $50->$48->$3F
  begin //Возвращает индекс окончания

    l := Length(s);
     if(l > 1) and (s[l-1]='1') then
     result:='0'
    else
    result:=s[l];

  end;

var
  rub: string;
  kop: string;
  h,x:integer;
begin {Возвращает число прописью с рублями и копейками}

  Result:=formatfloat('0.00',c);
  h:=length(Result);
  for X:=h to 18 do Result:=' '+Result;
  //Str(c: MaxPosition + 3: 2, Result);

  if Pos('E', Result) = 0 then //Если число можно представить в строке <>1E+99
  begin
    rub := TrimLeft(Copy(Result, 1, Length(Result) - 3));
    kop := Copy(Result, Length(Result) - 1, 2);
    Result := NumToStr(rub) + ' рубл'+ruble[strtoint(ending(rub))]
      + ' ' + kop + ' копе' + Kopeek[strtoint(ending(kop))];
    Result := UpperCase(Result[1]) + Copy(Result, 2, Length(Result) - 1);

  end;
end;
function GetSummaToText(r:real):string;
begin
initalize;
result:=RealToRouble(r);
end;
  
begin
   memo1.lines.text:=GetSummaToText(125.44);
end.

Скрипт после доработки позволит записывать число прописью на нужном Вам языке, тогда как возможности FastReport ограничены английским и русским.
Скрипт работает, но никак не соображу как его изменить, чтобы прописью писалось не 125.44, а значение из Reportnum.

pha1984 wrote:

Спс, помогите со вторым вопросом связанной с показом системной даты, смотрите скрипт на 4 поста выше.

var
  Timer: TTimer;

procedure Code_OnShow (Sender: string; Action: string);
begin
     Timer := TTimer.Create (nil);
     Timer.OnTimer := @OnTimer;
     Timer.Interval := 1000;
     Timer.Enabled := True;
end;

procedure OnTimer;
begin
     Code.Label5.Caption := FormatDateTime('c', Now);
     Code.Edit15.Text := FormatDateTime('c', Now);
end;

procedure Code_OnClose (Sender: string; Action: string);
begin
     Timer.Free;
end;

begin

end.
DriveSoft wrote:

Попробуйте так

ORDER BY tasks.dateCompletion, details.dateCompletion

Спасибо Дмитрий! Я до этого как-то не додумался. Почти также пробовал сделать, но вместо запятой писал AND. Увы, это ничего не дало, поэтому и обратился за помощью.

DriveSoft wrote:

Вконце запроса добавить

ORDER BY tasks.dateCompletion

А внутри tasks по details.dateCompletion (см. рисунок)?

СПАСИБО! И ещё вопрос: а как дописать, чтобы осуществлялась сортировка по датам? Сейчас записи выводятся в непонятном порядке (см. рисунок выше).

И вновь прошу помощи. Такой скрипт

SELECT
tasks.contentTask,
tasks.dateCompletion,
details.contentDetails,
details.dateCompletion,
(CASE WHEN ((SELECT Count(*) FROM details WHERE details.id_tasks=tasks.id AND details.status=1) > 0 OR details.status=1) then 'НА КОНТРОЛЕ' else  '' end)

FROM tasks

LEFT OUTER JOIN details ON details.id_tasks = tasks.id

даёт даты в виде 2015-07-14 00:00:00.000 (Результат на рисунке). А как получить 14.07.2015?
Это первый вопрос. И второй. Как к этому добавитьещё поля department.department, otdel.otdel, pozition.pozition, abonents.person если в таблице details есть поля id_department, id_otdel, id_pozition, id_abonents?

DriveSoft wrote:

kunar80
Для удаления записи нет необходимости перечислять поля

Спасибо, Дмитрий! Так работает.

Подскажите пожалуйста, что неправильно в запросе

DELETE
abonents.id_organization,
abonentsid.id_department,
abonents.id_otdel,
abonents.id_room,
abonents.id_position,
abonents.person,
abonents.phoneWork,
abonents.phoneMobile,
abonents.phoneHome,
abonents.phoneOther,
abonents.FAX,
abonents.emailWork,
abonents.emailHome,
abonents.tags

FROM abonents



WHERE id_organization = {ComboBox1}

Смотрите рисунок, будет понятнее, о чём речь.

Спасибо. Это работает.

По пункту 2 сейчас скрипт выглядит так:

procedure frmMain_TableGrid1_OnChange (Sender: string);
/////// Цвет фона ячейки грида при условии /////////////
    var
       i,c: integer;
    begin
         c := frmMain.TableGrid1.RowCount - 1;
         for i := 0 to c do
         begin
         if frmMain.TableGrid1.Cells[3,i] = 'НА КОНТРОЛЕ' then frmMain.TableGrid1.Cell[3,i].Color := $00BBBBFF;
         end;
    end;

Самостоятельно никак не получается дописать скрипт так, чтобы получилось, как на прикрепленном рисунке. Прошу помощи.

СПАСИБО!!!!!!

DriveSoft wrote:

1. У меня работает все так, как вы описали, открывается форма frmViewDetails

У меня тоже, ПОКА НЕ ЗАЛОГИНИШЬСЯ!

pha1984 wrote:

Можете оставить свой проект для примера?

http://myvisualdatabase.com/forum/misc. … download=1

121

(10 replies, posted in Russian)

pha1984 wrote:

Если не секрет то выложите свой проект для примера

http://myvisualdatabase.com/forum/misc. … download=1

DriveSoft wrote:

Приложите пожалуйста ваш проект, так будет проще помочь.

Проект прилагаю. Основных не решённых вопросов пока четыре:
1)    frmMain.TableGrid1
Enter и DoubleClik почему-то открывают форму редактирования, хотя прописан запрет и этого не должно быть. Т.е. должна открываться форма frmViewDetails, а редактирование только по кнопке редактирования.
2)    procedure frmMain_TableGrid1_OnChange
Здесь к раскраске ячеек со значением НА КОНТРОЛЕ хотелось бы добавить красный цвет этих ячеек при условии, что или сама задача должна быть выполнена сегодня, или в подчинённой таблице у этой задачи есть хотя бы одна подзадача, срок исполнения которой истекает именно сегодня. Т.е. сразу же после запуска проекта в таблице главной формы красным цветом выделены актуальные на сегодня задачи, розовым (как сейчас) – остальные со статусом НА КОНТРОЛЕ.
3)    frmMain .DateTimePicker3 и кнопка frmMain .ButtonSQL
Почти то же, что и пункт 2, т.е. показ в гриде  только тех задач, у которых хотя бы одна подзадача должна быть выполнена в установленный в DateTimePicker срок. Кнопку планирую спрятать,  а клик по ней навесить на кнопку поиска.
4)    frmAddTask.CheckBox1,  frmAddTask.CheckBox2 и frmAddDetail.CheckBox1 по ходу изменил на три состояния, следовательно возникла необходимость изменить вычисляемые поля statusControl2 (tasks), statusYes(tasks) и statusControl(details), т.к. скрипты  в них были написаны для чекбоксов на два состояния. Т.е. добавить в ячейку грида помимо НА КОНТРОЛЕ ещё и ВЫПОЛНЕНО.

В продолжение темы.

1. Как аналогично запросить список ЗАВТРАШНИХ именинников?
Меняю now на tomorrow, не работает.

t := SQLExecute('SELECT group_concat(person, char(13)) FROM abonents WHERE strftime(''%d.%m'', birthday)=strftime(''%d.%m'', ''tomorrow'')');

2. А можно ли в гриде поиском или запросом отобрать именинников по определённой дате независимо от года рождения?

DriveSoft wrote:

Данный скрипт не обращается к компоненту, а обращается непосредственно в базу данных, в вашем случае лучше создать вычисляемое поле:

(CASE WHEN implementation=1 then 'На контроле' else '' end)

А при трёх состояниях чекбокса как записать? Как втиснуть сюда implementation=NULL then 'Выполнено'?

Вопрос снят. Решено. Ошибка была в том, что в procedure frmMain_OnShow вначале нужно запустить формирование серийного номера и кода активации, а уже затем запускать проверку стартовой даты в реестре. У меня же было наоборот.