Freitag, 11. Dezember 2009

Datumsspielereien (Teil 5) / Date gadgets (Part 5)

Heute gibt es eigentlich nur einen kleinen Nachtrag.

Im 4. Teil der Datumsspielereien drehte es sich u. a. darum, wie wir die korrekte Kalenderwoche berechnen. Der umgekehrte Weg, aus einer Kalenderwoche wieder ein Datum zu generieren fehlte allerdings.

Wenn wir ein solches Datum berechnen sollen, dann müssen wir uns auf einen von sieben Tagen der Woche einigen. Der Einfachheit halber habe ich in der folgenden Beispielfunktion den Wochenbegin (=Montag) gewählt.

Die Funktion GetMondayFromCalWeek() erwartet maximal 2 Parameter. Wird kein zweiter Parameter (=Jahr) übergeben, so erfolgt die Datumsberechnung auf dem aktuellen Kalenderjahr sowie der als Parameter 1 übergebenen Kalenderwoche.

CLEAR
?GetMondayFromCalWeek(51)        && Für 2009: 14.12.2009
?GetMondayFromCalWeek(4,2010)    &&           25.01.2010

FUNCTION GetMondayFromCalWeek as Date
LPARAMETERS vWeek as Integer, vYear as Integer
   
    LOCAL ldDate as Date
   
    * // Wenn kein Jahr übergeben wurde, dann arbeiten wir mit dem aktuellen
    m.vYear    = IIF ( VARTYPE ( m.vYear ) <> [N],YEAR ( DATE () ) ,m.vYear )
    * // der 1.1. des gewählten Jahres stellt die Basis für die Berechnung   
    ldDate    = CTOD ( [01.01.] + ALLTRIM ( STR ( m.vYear ) ) )
    * // Wenn der 01.01. in der 1. Kalenderwoche liegt, dann ist alles gut,   
    * // andernfalls müssen wir 7 Tage hinzuaddieren.                       
    ldDate    = IIF ( WEEK ( ldDate,2,2 ) <> 1,ldDate + 7,ldDate )
    * // Den Montag der Woche des Datums berechnen und die Anzahl der Wochen
    * // hinzuaddieren. Dies ergibt den Montag der übergebenen Kalenderwoche
    RETURN ldDate - ( DOW ( ldDate,2 ) - 1 ) + ( ( m.vWeek - 1 ) * 7 )

ENDFUNC

Donnerstag, 3. Dezember 2009

Druckerstatus abfragen / Query printer status

Die Anzeige des aktuellen Zustands der verfügbaren Drucker kann für so manchen Anwender von essentieller Bedeutung sein, wenn es darum geht einen Ausdruck möglichst schnell in den Händen zu halten. Andererseits kann es nur von Vorteil sein, wenn bei einer Druckausgabe bereits im Vorfeld erkennbar ist, daß ein spezieller Drucker bspw. einen Papierstau hat, oder nur wenig Papier im Einzugschacht verfügbar ist.

Die Funktion APRINTER(myPrinterArray[,1]) liefert uns in einem Array den Druckernamen, den Anschluss, den Treiber, den Kommentar und den Standort.

APRINTER(laPrinters,1)
CLEAR
DISPLAY MEMORY LIKE laPrinters

Was fehlt ist die Information, ob der oder die Drucker auch tatsächlich verfügbar sind, oder ob gerade ein Druckjob abgearbeitet wird, oder ob der Drucker überhaupt verfügbar ist. Solche Informationen können wir jedoch über den Windows Management Service recht einfach abrufen.Detaillierte Infos zur Win32_Printer Klasse (Bestandteil der Windows Management Instrumentation) gibt es auf MSDN:

http://msdn.microsoft.com/en-us/library/aa394363(VS.85).aspx

Dort finden wir u.a. auch die Aufschlüsselung der Fehlernummern auf die wir gezielt reagieren können, wenn der Druckerstatus bspw. eine 1 (=Other) oder 9 (=Error) liefert. Im folgenden ein wenig Mustercode der über den Zugriff auf die WMI auskunft gibt:

LOCAL lcComputer as String, loWMIService as Object, ;
      loInstalledPrinters as Object, lcStatus as String, ;
      lcFont as String

* // Arbeitsvariablen initialisieren und WMI Objekt erzeugen
lcComputer          = [.]
loWMIService        = GETOBJECT([winmgmts:] + [{impersonationLevel=impersonate}!\\] + lcComputer + [\root\cimv2])
loInstalledPrinters = loWMIService.ExecQuery([SELECT * FROM Win32_Printer])
lcFont              = _screen.FontName
* // VFP Screen vorbereiten            
_screen.FontName    = [Courier New]
CLEAR 
?[Name] + SPACE(40) + [Status]
?REPLICATE([-],50)

* // Druckerobjekt auslesen            
FOR EACH loPrinter IN loInstalledPrinters

    ?PADR(loPrinter.Name,44,[ ])
    lcStatus = GetPrinterStatusAsText(loPrinter)
    ?? lcStatus

NEXT
* // VFP Screen zurücksetzen        
_screen.FontName = lcFont


FUNCTION GetPrinterStatusAsText as String
LPARAMETERS oPrinter as Object

    LOCAL lcReturn as String
    lcReturn = []

    DO CASE
    CASE oPrinter.PrinterStatus = 1
        * // Other
        lcReturn = [anderes        ]
    CASE oPrinter.PrinterStatus = 2
        * // Unknown
        lcReturn = [unbekannt      ]
    CASE oPrinter.PrinterStatus = 3
        * // Idle
        lcReturn = [bereit         ]
    CASE oPrinter.PrinterStatus = 4
        * // Printing
        lcReturn = [druckt         ]
    CASE oPrinter.PrinterStatus = 5
        * // Warming Up
        lcReturn = [aufwärmen      ]
    CASE oPrinter.PrinterStatus = 6
        * // Stopped Printing
        lcReturn = [gestoppt       ]
    CASE oPrinter.PrinterStatus = 7
        * // Offline
        lcReturn = [Offline        ]
    CASE oPrinter.PrinterStatus = 8
        * // Paused
        lcReturn = [pausierend     ]
    CASE oPrinter.PrinterStatus = 9
        * // Error
        lcReturn = [Fehler         ]
    CASE oPrinter.PrinterStatus = 10
        * // Busy
        lcReturn = [beschäftigt    ]
    CASE oPrinter.PrinterStatus = 11
        * // Not Available
        lcReturn = [nicht verfügbar]
    CASE oPrinter.PrinterStatus = 12
        * // Waiting
        lcReturn = [wartend        ]
    CASE oPrinter.PrinterStatus = 13
        * // Processing
        lcReturn = [verarbeiten    ]
    CASE oPrinter.PrinterStatus = 14
        * // Initialization
        lcReturn = [initialisieren ]
    CASE oPrinter.PrinterStatus = 15
        * // Power Save
        lcReturn = [Stromsparmodus ]
    CASE oPrinter.PrinterStatus = 16
        * // Pending Deletion
        lcReturn = [löscht Druckjob]
    CASE oPrinter.PrinterStatus = 17
        * // I/O Active
        lcReturn = [E/A aktiv      ]
    CASE oPrinter.PrinterStatus = 18
        * // Manual Feed
        lcReturn = [manuelle Zufuhr]
    ENDCASE
    * // Die Liste ggf. nach Bedarf erweitern
    IF INLIST(oPrinter.PrinterStatus,1,9)
        lcReturn = lcReturn + GetDetectedErrorStateAsText(oPrinter.DetectedErrorState)
    ENDIF
    RETURN lcReturn

ENDFUNC


FUNCTION GetDetectedErrorStateAsText as String
LPARAMETERS vErrorstate as Integer

    LOCAL lcReturn as String

    DO CASE
    CASE m.vErrorState = 0
        * // Unknown
        lcReturn = [Unbekannter Fehler]
    CASE m.vErrorState = 1
        * // Other
        lcReturn = [Anderer Fehler]
    CASE m.vErrorState = 2
        * // No Error
        lcReturn = [kein Fehler]
    CASE m.vErrorState = 3
        * // Low Paper
        lcReturn = [zu wenig Papier]
    CASE m.vErrorState = 4
        * // No Paper
        lcReturn = [kein Papier]
    CASE m.vErrorState = 5
        * // Low Toner
        lcReturn = [zu wenig Toner]
    CASE m.vErrorState = 6
        * // No Toner
        lcReturn = [kein Toner]
    CASE m.vErrorState = 7
        * // Door Open
        lcReturn = [Gehäuse geöffnet]
    CASE m.vErrorState = 8
        * // Jammed
        lcReturn = [Papierstau]
    CASE m.vErrorState = 9
        * // Service Requested
        lcReturn = [Kundendienst erforderlich]
    CASE m.vErrorState = 10
        * // Output Bin Full
        lcReturn = [Ausgabeschacht ist voll]
    CASE m.vErrorState = 11
        * // Paper Problem
        lcReturn = [Papier Problem]
    CASE m.vErrorState = 12
        * // Cannot Print Page
        lcReturn = [Seite kann nicht gedruckt werden]
    CASE m.vErrorState = 13
        * // User Intervention Required
        lcReturn = [Benutzereingriff notwendig]
    CASE m.vErrorState = 14
        * // Out Of Memory
        lcReturn = [Arbeitsspeicher voll]
    CASE m.vErrorState = 15
        * // Server Unknown
        lcReturn = [unbekannter Server]
    OTHERWISE
        lcReturn = [Unbekannt]
    ENDCASE
    RETURN     [(] + ALLTRIM(STR(m.vErrorState)) + [) ] + lcReturn

ENDFUNC