1

Arbeitstage berechenen

Guten Morgen,
hat jemand eine Idee für folgende Fragestellung?

Mit workdays(Datum1, Datum2) läßt sich die Anzahl der Arbeitstage zwischen Datum1 und Datum2 berechnen.
Ich kenne das Ausgangsdatum und die Zahl der Arbeitstage, muss also das zweite Datum mit diesen beiden bekannten Werten berechnen.

Geht das? Und wenn, wie?

Vielen Dank fürs Nachdenken, mir fällt's leider nicht ein.

33 Antworten

null
    • AxelE
    • vor 6 Jahren
    • Gemeldet - anzeigen
    Vielleicht so (Berechnungsfeld)?

    let Enddatum := Startdatum + Tage;
    workdays(Datum, Enddatum)

    Ach so, Tage wäre ein numerisches Feld.
    • Holzi
    • vor 6 Jahren
    • Gemeldet - anzeigen
    Das ist leider genau das Problem:
    Deine +Tage sind keine meine Arbeitstage (also nur Mo-Fr).
    Wenn ich diese Zahl addiere bekomme ich nicht das Enddatum, sondern das Enddatum minus Wochenenden.
    • Holzi
    • vor 6 Jahren
    • Gemeldet - anzeigen
    So ginge es vielleicht:
    Die bekannte Zahl der Arbeitstage sei x
    Anfangsdatum ist bekannt = Datum1
    Jetzt müsste eine Schleife durchlaufen werden die die "workdays" zählt wobei
    immer ein Tag als Datum2 draufgepackt wird. Bei jedem Durchgang müßten die errechneten workdays mit x verglichen werden. Wenn workdays = x muss das akteull letzte Datum in ein Feld geschrieben werden.

    Soweit die Idee, nur wie bekomme ich das hin?
    • AxelE
    • vor 6 Jahren
    • Gemeldet - anzeigen
    Ja, das war auch meine Überlegung. Leider funktioniert die schnell zusammengebastelte Formel nicht. Da ich im Moment leider keine Zeit habe, stelle ich sie als Anregung trotzdem mal hier rein:

    let TagDat := Startdatum;
    let ABTage := Arbeitstage;
    let WETage := 0;
    for i in range(1, ABTage) do
    if weekday(TagDat) < 1 or > 5 then
    WETage = WETage + 1
    end;
    TagDat = TagDat + 1
    end;
    let Gesamttage := Arbeitstage + WETage;
    Startdatum + Gesamttage
    • AxelE
    • vor 6 Jahren
    • Gemeldet - anzeigen
    Sorry, hatte vorhin was Dringendes zu erledigen. Der gepostete Code war nur ein unfertiges Fragment. Grundidee war halt, in einer Schleife den Wochentag abzufragen, im Falle von Sa/So (weekday > 4 oder weekdayName = "Samstag"/"Sonntag") einen Zähler mitlaufen zu lassen (WETage), der am Ende einfach zu den Arbeitstagen addiert wird. Aus dem Ergebnis (Gesamttage) ließe sich dann das Enddatum berechnen. Codetechnisch umgesetzt kriege ich das auf die Schnelle aber auch nicht. Ich versuche es später noch mal, sofern sich zwischenzeitlich keine Lösung ergibt.
    • Leonid_Semik
    • vor 6 Jahren
    • Gemeldet - anzeigen
    Ich schlage folgendes vor:
    Angenommen, es gibt ein Feld "Startdatum" und ein Feld "Dauer"


    let myComment:="Wenn Anfangsdatum auf Samstag oder Sonntag fällt, wird es auf Nächsten Montag verlegt";
    let myDate := switch weekday(Startdatum) do
    case 5:
    Datum + 2
    case 6:
    Datum + 1
    default:
    Datum
    end;
    let myComment:="Arbeitswoche hat 5 Tage. Wenn Enddatum nicht übers Wochenende läuft, dann ist die Anzahl Wochenenden 0, wenn doch, dann werden noch 2 Wochenendtage dazugerechnet. Ansonsten wir die abgerundete Anzahl der Arbeitswochen mal 2 genommen";
    let myWeekends := if weekday(myDate) + Dauer < 5 then
    0
    else
    if weekday(myDate) + Dauer < 9 then
    2
    else
    2 * floor(Dauer / 5)
    end
    end;
    let myComment:="Das Enddatum wird aus neuen Anfangsdatum plus Anzahl der Tage plus Wochenendtage berechnet";
    let ENDE := date(myDate + Dauer + myWeekends);
    let myComment:="wenn das Ergebnis aufs Wochenende fällt, wird automatisch nächsten Montag genommen"
    switch weekday(ENDE) do
    case 5:
    ENDE + 2
    case 6:
    ENDE + 1
    default:
    ENDE
    end


    Grüße
    Leo
    • Holzi
    • vor 6 Jahren
    • Gemeldet - anzeigen
    Hallo Leo,
    wie immer: Genial, war doch nicht so "einfach" wie ich es mir gedacht hatte
    Ganz herzlichen Dank!!
    Noch ein kleiner Schönheitsfehler
    Beispiel 24.01.2018 bis 27.02.2018 ergibt mit workdays 25 Arbeitstage.
    Wenn ich das gleiche Startdatum nehme und die 25 AT als Dauer einsetze,
    wird als Enddatum der 28.02.2018 errechnet. Das gilt auch für andere Zeiträume. Es immer ein Tag "zuviel".
    Nicht tragisch, aber vielleicht gibt es da noch eine kleine Korrektur im Skript?

    @AxelE: Auch für den Vorschlag herzlichen Dank.
    • Holzi
    • vor 6 Jahren
    • Gemeldet - anzeigen
    Falls sich jemand fragt, was da ganze soll:
    Bei bestimmten Bestell/Liefervorgängen ist die Zahl der Arbeitstage, die vergehen immer ziemlich gleich (lang). Mit diesem Skript kann ich vom Ausgangsdatum ausgehend im Kalender schon in etwa die Erledigung vormerken (kontrollieren).
    • Leonid_Semik
    • vor 6 Jahren
    • Gemeldet - anzeigen
    Ich finde die Idee von AxelE sehr interessant. Und die Formel wäre dann:

    var myDate := switch weekday(Datum) do
    case 5:
    Datum + 2
    case 6:
    Datum + 1
    default:
    Datum
    end;
    for II from 1 to Tage do
    myDate := switch weekday(myDate) do
    case 5:
    myDate + 3
    default:
    myDate + 1
    end
    end;
    switch weekday(myDate) do
    case 5:
    myDate + 2
    case 6:
    myDate + 1
    default:
    myDate
    end

    Leo
    • Holzi
    • vor 6 Jahren
    • Gemeldet - anzeigen
    Ja, Super, funktioniert einwandfrei. UND das Problem mit einem Tag zuviel (siehe post "Februar 27, 2018 um 3:15 pm" hat sich - warum auch immer - auch erledigt.
    Danke an Euch beide
    • Holzi
    • vor 6 Jahren
    • Gemeldet - anzeigen
    @AxelE und @Leo
    Ich habe mal versucht, dass Thema nochmal anders anzugehen:
    ______________________________
    let D1 := Datum1;
    let D2 := Datum1 + 1;
    let D := Dauer;
    let WD := 0;
    for i from WD to Dauer do
    WD = workdays(D1, D2);
    D2 = D2 + 1
    end;
    D2
    ______________________________
    Sieht gut aus, klappt aber nicht; keine Fehlermeldung.
    D2 ist so Datum1+1, als wenn die Schleife gar nicht durchlaufen würde.
    Wenn ich
    WD := workdays(D1, D2);
    schreibe, also Zuweisung := dann ist D2 Dauer

    Wahrscheinlich Gedanken- oder Formulierungsfehler?
    Ich versuche zu lernen....
    Würde mich über Anregungen freuen, Danke
    • Leonid_Semik
    • vor 6 Jahren
    • Gemeldet - anzeigen
    Hervorragende Idee!
    die Formel dazu wäre:

    var D := Datum1;
    let II := 1;
    while II < 5 do
    D := D + 1;
    II := switch workdays(Datum1, D) do
    case Dauer:
    6
    default:
    1
    end
    end
    ;
    D


    Grüße
    Leo
    • AxelE
    • vor 6 Jahren
    • Gemeldet - anzeigen
    Super. Wenn das funktioniert (wovon ich einfach mal ausgehe), dann sollte man die Lösung vielleicht in die Beispieltabelle mit den Datumsfunktionen aufnehmen. Denn, wie einer der Ninox-Leute bei dem Webinar gestern richtig sagte: Eine solche Berechnung anhand eines Startdatums und einer bestimmten Zahl an Werktagen ist ja für diverse, alltägliche Anwendungsszenarien denkbar: Urlaubsende, voraussichtliches Liefer- oder Produktionsdatum ...

    Wobei: Wie sieht es eigentlich mit Feiertagen aus? Die werden nicht berücksichtigt, oder? Für eine immer und an jedem Standort zuverlässig funktionierende Lösung müsste man wahrscheinlich auch noch eine Tabelle mit den jeweils gültigen Feiertagsdaten erstellen und innerhalb des Codes zusätzlich abfragen. Oder sehe ich das falsch? Existiert so eine Tabelle schon irgendwo?
    • Holzi
    • vor 6 Jahren
    • Gemeldet - anzeigen
    Das Lob geht runter wie Öl :)
    Warum mein Skript nicht funktioniert hat, weiß immer noch nicht, aber Dein's funktioniert einwandfrei.
    Danke
    • Leonid_Semik
    • vor 6 Jahren
    • Gemeldet - anzeigen
    Mit Feiertagen wäre es kein Problem. Hauptproblem für mich, wie kriege ich alle Feiertage in die Datenbank, ohne jedes Jahr neu anzufangen. Es gibt ein Wikipedia Eintrag :
    https://de.wikipedia.org/wiki/Gesetzliche_Feiertage_in_Deutschland
    Theoretisch kann man versuchen eine Vorlage zu generieren.
    • AxelE
    • vor 6 Jahren
    • Gemeldet - anzeigen
    Zur Berechnung der beweglichen Feiertage benötigt man eigentlich nur das Datum des Ostersonntags. Außer beim Buß- und Bettag, das ist immer der Mittwoch vor dem 23.11.

    Man müsste in einer entsprechenden Tabelle aber auch noch die Bundesländer berücksichtigen. Das macht die Sache etwas komplexer.
    • Holzi
    • vor 6 Jahren
    • Gemeldet - anzeigen
    Das wäre, glaube ich kein Problem.
    Die "festen" Feiertage =immer gleichen Datum im Jahr, könnte man in eine Tabelle schreiben und jedes Jahr neu zugreifen + Jahreszahl. Diese Tabelle könnte man so gestalten, dass die Feiertage mit einem Auswahlfeld passend für die eigenen Bedürfnisse (Bundesland) anzupassen.
    Das Problem sind die "beweglichen" Feiertag = jedes Jahr anders :(
    Dieses Jahr z.B.
    KarfreitagFreitag30.3.2018
    OstersonntagSonntag1.4.2018
    OstermontagMontag2.4.2018
    Christi HimmelfahrtDonnerstag10.5.2018
    PfingssonntagSonntag20.5.2018
    PfingsmontagMontag21.5.2018
    FronleichnamDonnerstag31.5.2018
    Die werden ausgehend von Ostersonntag sehr einfach (!!) berechnet.
    Aber:
    Die Formel für Ostersonntag (müsste für Ninox angepasst werden) lautet:
    In A1 steht das Jahr, also 2018

    =DATUM(A1;3;1)+REST((255-11*REST(A1;19)-21);30)+21+(REST((255-11*REST(A1;19)-21);30) + 21>48)+6-REST(A1+GANZZAHL(A1/4)+REST((255- 11*REST(A1;19)- 21);30)+21+(REST((255-11*REST(A1;19)-21);30)+21>48)+1;7)

    Ich weiß im Augenblick nicht, wie ich diese Formel für Ninox umbauen soll, da mir die Funktionen Datum(), Rest() und Ganzzahl fehlen.

    Mit der Formel in Ninox wäre das Ganze recht einfach.
    • Holzi
    • vor 6 Jahren
    • Gemeldet - anzeigen
    Ich hatte bei Funktions-u. Sprachreferenz gepostet:
    In Excel gibt es die Funktion
    Rest() oder Mod() im Englischen,
    und die Funktion Ganzzahl() oder integer() im Englischen.
    In Ninox finde ich nichts entsprechendes – oder kann nicht richtig gucken….
    Hat jemand eine Idee, wie diese beiden Funktionen in Ninox aussehen könnten / nachgebildet werden könnten?

    Birger hat geantwortet:
    mod() gibt es bei Ninox so “%”:
    –––
    8 % 5 => 3
    –––
    floor(17.567) => 17
    –––

    Bislang hab ich das nicht in die Formel einbauen können.
    Vielleicht schaftt es jemand von Euch?
    • AxelE
    • vor 6 Jahren
    • Gemeldet - anzeigen
    Moin allerseits, da offenbar noch keine Datenbank bzw. Tabelle mit den Feiertagen existiert, habe ich selber mal eine erstellt. Es handelt sich um eine einfache zweidimensionale Tabelle mit allen Feiertagen von 2000 bis 2100 und der nach Bundesländern unterschiedenen Angabe, ob der Tag dort offiziell arbeitsfrei ist oder nicht. Lokale und regionale Regelungen, wie z. B. in Bayern, habe ich nicht berücksichtigt. Wer von diesen Ausnahmen betroffen ist, weiß es in der Regel ja und kann die entsprechenden Einträge manuell ändern.

    Die Tabelle beinhaltet aber nicht nur die gesetzlichen Feiertage, an denen in mindestens einem Bundesland offiziell arbeitsfrei ist, sondern auch weitere kirchliche Feier- und besondere Tage wie Rosenmontag, Muttertag und Heiligabend, die hinsichtlich der Arbeitszeiten individuell gehandhabt werden oder an die man vielleicht aus anderen Gründen erinnert werden möchte.

    Und warum von 2000 bis 2100? Nun, aus einem früheren EDV-Leben weiß ich, dass man nie zu viele Daten haben kann, weil sich irgendwann bei irgendwem Bedarfssituationen ergeben können, die man nicht auf dem Zettel hatte. Außerdem wäre der Arbeitsaufwand für zehn Jahre derselbe gewesen. Und kürzen kann man ja immer ...

    Aber wie gesagt: Es ist nur eine einfache, statische Tabelle mit den Feiertagsdaten. Sie enthält keinerlei Formeln oder Code und ist lediglich als Grundlage für eigene Anwendungen und Auswertungen gedacht. Für den vorliegenden Fall der Berechnung von Arbeitstagen sollte sie genügen (ich vermute, dass eine direkte Abfrage nach Datum u. U. sogar schneller ist als aufwändige Berechnungsformeln). Darüber hinaus sind aber auch viele andere Auswertungen denkbar.

    Also, falls jemand Interesse an dieser Tabelle hat: Ich habe sie im XLS-, CSV- und Ninox-DB-Format zum Download auf einen Server gelegt. So kann jeder das Format wählen, das er braucht.

    http://cloud.copytexter.com/index.php/s/i78xiAdnEPTzP8d

    Vielleicht könnt ihr was damit anfangen.
    • Leonid_Semik
    • vor 6 Jahren
    • Gemeldet - anzeigen
    Hallo Axel,
    Vielen Dank für die Mühe. Hilft bestimmt bei Projektmanagement. Eine Anmerkung: die Datums sind als Jahrestage markiert, so kommt man in Kalendersnsicht zu Unmengen an Einträgen. Habe jetzt Jahrestag als nein gesetzt.

    Grüße
    Leo
    • AxelE
    • vor 6 Jahren
    • Gemeldet - anzeigen
    Hallo Leo, danke für dein Feedback. Freut mich, wenn's hilft. Aber "Unmengen an Einträgen" im Kalender? Bei mir sind es 25 pro Jahr, für jeden "Feiertag" einen. Fand ich jetzt nicht zu viel. Aber natürlich soll sich die DB jeder nach eigenen Vorstellungen anpassen. Man könnte sich z. B. nur die gesetzlich freien Wochentage seines Bundelandes im Kalender anzeigen lassen. Oder was auch immer. Wie gesagt: Die Daten sind nur als Grundlage für eigene Anwendungen und Auswertungen jeglicher Art gedacht. Also: Mach damit, was immer du willst. ;)
    • AxelE
    • vor 6 Jahren
    • Gemeldet - anzeigen
    Ach so, die Site verfügt übrigens über ein SSL-Zertifikat. Ihr solltet also per https adressieren (kann das oben leider nicht mehr ändern):

    https://cloud.copytexter.com/index.php/s/i78xiAdnEPTzP8d
    • Holzi
    • vor 6 Jahren
    • Gemeldet - anzeigen
    Guten Abend (Ihr beiden),
    ich habe es tatsächlich hinbekommen, die Osterformel (Berechnung des Ostersonntags) für Ninox so anzupassen, dass sie funktioniert. Mit dem ostersonntag lassen sich dann die davon abhängigen Feiertage berechnen.
    Die Datenbank(Tabelle) habe ich auf Dropbox hochgeladen:
    https://www.dropbox.com/s/x13qw0gxb72aqr0/Feiertage%20berechnen.ninox?dl=0
    Für die Berechnung von Buss- und Bettag gilt die Osterformel nicht sondern eine andere, einfachere. Da liegt bei mir zur Zeit der Wurm:
    In diesem Skriptabschnitt habe ich offensichtlich einen Fehler, ich weiß nur nicht welchen.

    if Monat = 3 then
    alert(text(Monat));
    let Tageszahl1 := (33 - number(Tag)) % 7;
    'Buss- und Bettag' = date(number(Jahr), 11, 22) - Tageszahl1
    end;
    if Monat = 4 then
    alert(text(Monat));
    let Tageszahl2 := (30 - number(Tag)) % 7;
    'Buss- und Bettag' = date(number(Jahr), 11, 22) - Tageszahl2
    end

    Vielleicht habt Ihr Lust und Zeit mal draufzuschauen.
    Danke
    Ps: Dass, das Ganze durch die Tabelle von AxelE hinfällig ist, ist klar, aber ich möchte es trotzdem hinbekommen. :))
    • Holzi
    • vor 6 Jahren
    • Gemeldet - anzeigen
    Ach so:
    alert(text(Monat));
    habe ich eingebaut um den Fehler zu finden. Egal ob März oder April, hier wird immer "4" angezeigt.
    • Holzi
    • vor 6 Jahren
    • Gemeldet - anzeigen
    @AxelE Ich glaube in der Tabelle ist ein Fehler:
    Gründonnerstag ist in keinem Bundesland ein Feiertag, im Feld "gesetzlich" steht aber "ja"??
    Ich habe übrigens auch "Unmengen" an Einträgen im Kalender. Rausnehmen von "Jahrestag" beseitigt das Problem.

Content aside

  • 1 „Gefällt mir“ Klicks
  • vor 4 JahrenZuletzt aktiv
  • 33Antworten
  • 12047Ansichten
  • 1 Folge bereits