PBToolboxAI v4 ← Site

scheduler — u_pbt_scheduler #

← Référence des composants · Sommaire du guide

Un calendrier à la manière d'Outlook : vues jour, semaine de travail, semaine, mois et agenda, bande « journée entière », glisser-déposer pour déplacer et redimensionner, ressources côte à côte, catégories de couleur, et des cartes et des info-bulles écrites par modèles. Il se remplit rendez-vous par rendez-vous, ou d'un seul appel depuis un DataStore — et chaque geste de l'utilisateur vous rend la ligne à mettre à jour.

▶ Le voir en vrai — Application de démonstration, tuile Scheduler : l'aperçu, le code qui le produit et cette page, côte à côte.


En bref #

Userobjectu_pbt_scheduler
Classes d'itemsn_pbt_scheduler_appointment (un rendez-vous, of_appointment) · n_pbt_scheduler_resource (une ressource, of_resource) · n_pbt_scheduler_category (une catégorie, of_category)
Sert àPlanning d'une équipe, réservation de salles ou de machines, agenda d'un commercial, rendez-vous de patients — tout ce qui se pose sur des jours et des heures
Limite en mode démoLes 12 premiers rendez-vous de la plage à l'écran, par heure de début ; les autres restent en mémoire sans être affichés — voir le mode démo

Démarrage rapide #

// open event of the window : a few appointments of the week, in one repaint
uo_sched.of_set_redraw(/*on*/ false)
uo_sched.is_date = "2026-09-21"

// A colour category, then the appointments : a key, a subject, a start and an end
uo_sched.of_add_category(/*key*/ "customer", /*label*/ "Customer", /*color*/ RGB(216, 90, 48))
uo_sched.of_add_appointment(/*key*/ "a1", /*subject*/ "Weekly meeting", /*start*/ "2026-09-21 09:00", /*end*/ "2026-09-21 10:00")
uo_sched.of_appointment(/*key*/ "a1").is_location = "Room 3"
uo_sched.of_add_appointment(/*key*/ "a2", /*subject*/ "ACME visit", /*start*/ "2026-09-23 14:00", /*end*/ "2026-09-23 16:30")
uo_sched.of_appointment(/*key*/ "a2").is_category = "customer"

// Dates only : an all-day appointment, both days included
uo_sched.of_add_appointment(/*key*/ "a3", /*subject*/ "Trade fair", /*start*/ "2026-09-24", /*end*/ "2026-09-25")
uo_sched.of_appointment(/*key*/ "a3").ib_all_day = true
uo_sched.of_set_redraw(/*on*/ true)
// ue_appointment_opened event of uo_sched : (string as_key)
// A double-click, or Enter on the selected appointment : open YOUR editor
wf_edit_appointment(as_key)

Comprendre le calendrier #

Les vues #

is_view choisit la vue, is_date le jour autour duquel elle se construit : sa semaine, son mois. L'utilisateur change l'une et l'autre depuis la barre d'outils du composant (Aujourd'hui, précédent, suivant, menu des vues) — les deux propriétés se relisent en direct, et ue_view_changed / ue_date_changed le disent, que le changement vienne de l'utilisateur ou de votre code.

VueCe qu'elle montre
VIEW_DAYUn jour sur une grille horaire
VIEW_WORK_WEEKLes jours ouvrés de la semaine (is_work_days) — la vue par défaut
VIEW_WEEKLes sept jours, à partir de ii_first_day_of_week
VIEW_MONTHSix semaines ; un rendez-vous de plusieurs jours s'étire en barre sur ses jours
VIEW_AGENDAUne liste, jour par jour, sur ii_agenda_days jours

Les dates #

Une date voyage en texte, "yyyy-mm-dd hh:mm" — dans les méthodes, les propriétés et les événements. C'est une heure locale flottante : ni fuseau horaire, ni heure d'été ; "2026-09-22 09:00" s'affiche à 09:00, sur tous les postes.

// Local variables
datetime ldt_start

// A "yyyy-mm-dd hh:mm" text back into a PowerBuilder datetime
ldt_start = DateTime(Date(Left(as_start, 10)), Time(Mid(as_start, 12)))

La bande « journée entière » #

Au-dessus de la grille horaire des vues jour et semaine, une bande reçoit les rendez-vous ib_all_day et ceux qui durent 24 heures ou plus : un séminaire de trois jours y tient en une barre au lieu d'écraser trois colonnes. ib_all_day_band = false la retire. Dans la vue mois, ces rendez-vous sont des barres qui traversent leurs jours ; les autres, une ligne écrite par is_month_template.

Les rendez-vous d'un DataStore #

of_from_datastore(ids) charge le calendrier d'un seul appel : une ligne = un rendez-vous, et sa clé est son numéro de ligne — c'est elle que chaque événement vous rend, prête pour SetItem. Une colonne joue un rôle quand elle en porte le nom, ou quand of_map le lui donne :

RôleNoms reconnus sans of_map
ROLE_SUBJECTsubject, title
ROLE_START · ROLE_ENDstart, start_date, starts · end, end_date, ends
ROLE_ALL_DAY · ROLE_READ_ONLYall_day, allday · read_only, readonly
ROLE_KEY · ROLE_LOCATION · ROLE_ORGANIZER · ROLE_DESCRIPTION · ROLE_RESOURCE · ROLE_CATEGORY · ROLE_STATUS · ROLE_RECURRING · ROLE_PRIVATE · ROLE_REMINDER · ROLE_CANCELLEDle nom du rôle : key, location, organizer, description, resource, category, status, recurring, private, reminder, cancelled

Ressources et regroupement #

Une ressource est ce sur quoi on réserve : une personne, une salle, une machine (of_add_resource). Un rendez-vous la nomme par is_resource. Avec is_group_by = GROUP_RESOURCE, chaque jour des vues jour et semaine se divise en une colonne par ressource, et glisser une carte dans une autre colonne change sa ressource — ue_appointment_moved la rend dans as_resource. ib_visible = false sur une ressource masque sa colonne et ses rendez-vous, comme décocher un calendrier dans Outlook.

Couleurs, catégories et statut #

La couleur d'une carte se décide dans cet ordre : l'il_accent posé sur ce rendez-vous, puis la couleur de sa catégorie (of_add_category, is_category), puis celle de sa ressource, puis l'accent du thème. Le liseré de gauche dit le statut (is_status, le « Afficher comme » d'Outlook : occupé, provisoire, libre, absent, ailleurs) ; un rendez-vous ib_cancelled est dessiné creux, et ib_recurring, ib_private, ib_reminder posent un petit signe sur la carte.


Propriétés #

PropriétéTypeDéfautRôle
is_viewstringVIEW_WORK_WEEKLa vue affichée (VIEW_*). Relue en direct : l'utilisateur la change depuis la barre d'outils. La poser lève ue_view_changed, comme le menu des vues (rien si la vue ne change pas)
is_datestringaujourd'huiLe jour affiché, "yyyy-mm-dd" : la vue se construit autour (sa semaine, son mois). Relue en direct : les flèches la déplacent. Une fois posée, is_now ne la déplace plus ; "" rend la vue à aujourd'hui
is_nowstring""« Maintenant », pour la ligne de l'heure courante et le bouton Aujourd'hui : "" = l'horloge du poste ; "yyyy-mm-dd hh:mm" la fige (démonstration, test, rejeu). Tant que is_date n'a jamais été posée, la vue va à son jour
ii_first_day_of_weekinteger1Premier jour de la semaine, en numéros ISO comme is_work_days : 1 = lundi … 7 = dimanche ; 0 est accepté pour dimanche
is_work_daysstring"1|2|3|4|5"Les jours ouvrés, numéros ISO joints par | (1 = lundi … 7 = dimanche, 0 accepté pour dimanche) : ils forment la semaine de travail, les autres sont grisés
is_work_start · is_work_endstring"08:00" · "17:00"Les heures de travail, "hh:mm" : le reste de la journée est grisé
is_day_start · is_day_endstring"00:00" · "24:00"Les heures que la grille horaire montre ; ce qui tombe en dehors est compté au bord de sa colonne (« ▲ 1 plus tôt », « ▼ 1 plus tard »), avec ce que le défilement cache au-dessus ou au-dessous de la vue ; un clic sur le repère amène le rendez-vous caché le plus proche
ii_slot_minutesinteger30Le pas de la grille en minutes : 5, 10, 15, 20, 30 ou 60. Un glisser s'y aligne
ii_hour_heightinteger48La hauteur d'une heure, en pixels
is_scroll_timestring"08:00"L'heure où la grille se place à l'ouverture d'une vue
ib_show_nowbooleantrueLa ligne rouge de l'heure courante
ib_toolbarbooleantrueLa barre d'outils : Aujourd'hui, précédent, suivant, le titre, le menu des vues
ib_week_numbersbooleanfalseLes numéros de semaine ISO, dans le coin de la grille horaire et devant chaque ligne du mois
ib_read_onlybooleanfalseRien ne se déplace, ne se redimensionne ni ne se crée à la souris ; Suppr ne demande plus rien
ib_all_day_bandbooleantrueLa bande « journée entière » au-dessus de la grille horaire
ib_tooltipsbooleantrueL'info-bulle de chaque rendez-vous, écrite par les modèles d'info-bulle
ib_veto_changesbooleanfalseDemande avant d'appliquer un déplacement ou un redimensionnement : lève ue_appointment_changing, qui peut refuser
is_card_templatestring"[b]{subject}[/b]{?location}; {location}{/location}"Le modèle de la carte : vues jour et semaine, agenda, barres du mois — voir Les modèles
is_month_templatestring"{!all_day}{start} {/all_day}{subject}"Une ligne de la vue mois, pour un rendez-vous contenu dans un jour
is_tooltip_title_templatestring"{subject}"Le titre de l'info-bulle d'un rendez-vous
is_tooltip_templatestringl'heure, le lieu, l'organisateurLe texte de l'info-bulle d'un rendez-vous — voir Les modèles
is_group_bystringGROUP_NONEGROUP_RESOURCE : une colonne par ressource sous chaque jour, plus une colonne (aucune) à la fin quand un rendez-vous n'a pas de ressource connue du calendrier
is_filterstring""N'affiche que les rendez-vous qui contiennent ce texte (sujet, lieu, organisateur, description, champs) ; "" les montre tous
is_time_formatstring"hh:mm"L'écriture d'une heure : "hh:mm", "h:mm AM/PM"… (jetons de Les modèles)
ii_agenda_daysinteger7Le nombre de jours que liste la vue agenda
is_theme_stylestring""Style visuel du composant (constantes THEME_STYLE_*) ; vide = celui de l'application, suivi à chaque changement
is_theme_modestring""Variante claire ou sombre (constantes THEME_MODE_*) ; vide = celle de l'application, suivie à chaque changement
il_theme_accentlong-1Couleur d'accent de ce composant (-1 = l'accent de l'application, ou celui du thème)
is_tooltipstring""Info-bulle simple du composant (un rendez-vous a la sienne, écrite par les modèles)
is_super_tooltip_titlestring""Titre de l'info-bulle enrichie (prend le pas sur is_tooltip)
is_super_tooltip_textstring""Texte de l'info-bulle enrichie (balisage riche accepté)
is_super_tooltip_imagestring""Image de l'info-bulle enrichie

Propriétés d'un rendez-vous #

Un rendez-vous se pilote par son handle, of_appointment("clé") — créé au premier accès, il reste valable ensuite. Une propriété lue demande au composant ce qu'elle vaut maintenant : après un glisser, is_start et is_end disent déjà où l'utilisateur l'a déposé.

// A handle used once fits on one line
uo_sched.of_appointment(/*key*/ "a1").is_status = n_pbt_scheduler_appointment.STATUS_TENTATIVE
PropriétéTypeDéfautRôle
is_subjectstringcelui d'of_add_appointmentLe sujet, ce que la carte montre d'abord ({subject})
is_start · is_endstringceux d'of_add_appointmentDébut et fin, "yyyy-mm-dd hh:mm", fin exclusive ; pour une journée entière, des dates "yyyy-mm-dd", les deux jours inclus. Une autre écriture (22/09/2026 09:00) est gardée mais jamais dessinée
ib_all_daybooleanfalseOccupe des journées entières : dessiné dans la bande « journée entière »
is_location · is_organizer · is_descriptionstring""Le lieu ({location}), l'organisateur ({organizer}), un texte plus long ({description})
is_resourcestring""La clé de sa ressource : sa colonne quand le calendrier regroupe par ressource, sa couleur quand il n'a pas de catégorie
is_categorystring""La clé de sa catégorie : la couleur de la carte
is_statusstringSTATUS_BUSYLe « Afficher comme » d'Outlook (STATUS_*), dessiné par le liseré de gauche
ib_recurring · ib_private · ib_reminderbooleanfalsePetits signes sur la carte : une périodicité, un rendez-vous privé, un rappel
ib_cancelledbooleanfalseUn rendez-vous annulé est dessiné creux
ib_read_onlybooleanfalseL'utilisateur ne peut ni le déplacer, ni le redimensionner, ni demander sa suppression
ib_visiblebooleantrueLe masque sans le retirer

Comme tout item, un rendez-vous porte aussi l'info-bulle commune (is_tooltip, is_super_tooltip_title, is_super_tooltip_text, is_super_tooltip_image) — elle remplace alors celle des modèles — et les couleurs d'item : il_accent recolore la carte et son liseré, il_back_color, il_text_color, il_back_color_hover et il_text_color_hover la peignent au repos et au survol.

Propriétés d'une ressource et d'une catégorie #

PropriétéHandleRôle
is_labeln_pbt_scheduler_resourceLe nom affiché au-dessus de sa colonne quand le calendrier regroupe par ressource ({resource_label})
il_colorn_pbt_scheduler_resourceLa couleur de ses rendez-vous qui n'ont pas de catégorie ; -1 = l'accent
ib_visiblen_pbt_scheduler_resourcefalse masque sa colonne et ses rendez-vous
is_labeln_pbt_scheduler_categorySon nom ({category_label})
il_colorn_pbt_scheduler_categoryLa couleur de ses rendez-vous ; -1 = l'accent. Une catégorie n'est pas dessinée pour elle-même : l'info-bulle et les cinq couleurs d'item qu'elle hérite sont gardées et relues, sans effet visible

Constantes #

FamilleConstantesPortées par
VueVIEW_DAY, VIEW_WORK_WEEK, VIEW_WEEK, VIEW_MONTH, VIEW_AGENDAle composant (is_view)
RegroupementGROUP_NONE, GROUP_RESOURCEle composant (is_group_by)
Rôle d'une colonneROLE_KEY, ROLE_SUBJECT, ROLE_START, ROLE_END, ROLE_ALL_DAY, ROLE_LOCATION, ROLE_ORGANIZER, ROLE_DESCRIPTION, ROLE_RESOURCE, ROLE_CATEGORY, ROLE_STATUS, ROLE_RECURRING, ROLE_PRIVATE, ROLE_REMINDER, ROLE_CANCELLED, ROLE_READ_ONLYle composant (of_map)
StatutSTATUS_BUSY, STATUS_TENTATIVE, STATUS_FREE, STATUS_OOF, STATUS_ELSEWHEREle handle de rendez-vous (is_status)

Les constantes se lisent sur l'objet qui les porte : u_pbt_scheduler.VIEW_MONTH pour une propriété du composant, n_pbt_scheduler_appointment.STATUS_OOF pour une propriété de rendez-vous.


Méthodes #

Rendez-vous #

MéthodeRôle
of_add_appointment (string as_key, string as_subject, string as_start, string as_end)Ajoute un rendez-vous : sa clé (unique), son sujet, son début et sa fin "yyyy-mm-dd hh:mm". Tout le reste passe par son handle. Rend 0 une fois ajouté, -5 quand la clé est vide, contient / ou `, ou est **déjà prise** (un rendez-vous ne se met pas à jour par là : son handle le fait), ou quand le début — ou une fin donnée — n'est pas écrit yyyy-mm-dd ou yyyy-mm-dd hh:mm (String(ldt) écrit 22/09/2026 sur un poste français : prenez la surcharge datetime), -2` quand le composant n'est pas créé
of_add_appointment (string as_key, string as_subject, datetime adt_start, datetime adt_end)La même, depuis deux datetime ; une fin nulle vaut le début. Pour une journée entière, la fin est le dernier jour lui-même, inclus : deux fois la même date = un jour. Rend 0 une fois ajouté, -5 quand la clé est vide, contient / ou ` ou est déjà prise, ou quand le début est nul, -2` quand le composant n'est pas créé
of_appointment (string as_key)Le handle d'un rendez-vous (n_pbt_scheduler_appointment), créé au premier accès — voir Propriétés d'un rendez-vous
of_remove_appointment (string as_key)Retire un rendez-vous. Rend 0 une fois retiré, -5 quand le calendrier n'a aucun rendez-vous de cette clé, -2 quand le composant n'est pas créé
of_clear_appointments ( )Retire tous les rendez-vous ; ressources, catégories et options restent. Rend 0 une fois envoyé, -2 quand le composant n'est pas créé
of_set_field (string as_key, string as_field, string as_value)Donne à un rendez-vous un champ à vous, pour les modèles : après of_set_field("a1", "customer", "ACME"), {customer} écrit ACME sur sa carte. Rend 0 une fois posé, -5 quand le champ est vide ou que le calendrier n'a aucun rendez-vous de cette clé, -2 quand le composant n'est pas créé
of_get_field (string as_key, string as_field)Lit en direct un champ d'un rendez-vous : un des vôtres (of_set_field) ou une colonne du DataStore dont il vient ; "" quand il n'en a pas

DataStore #

MéthodeRôle
of_from_datastore (datastore ads)Le pont DataStore : une ligne = un rendez-vous, sa clé = son numéro de ligne, chaque colonne = un champ des modèles. Remplace les rendez-vous affichés. Rend 0 une fois chargé, -5 quand le DataStore n'est pas valide ou n'a aucune colonne, -2 quand le composant n'est pas créé
of_map (string as_role, string as_column)Donne un rôle (ROLE_*) à une colonne dont le nom ne le dit pas : of_map(ROLE_SUBJECT, "title_text"). Avant ou après of_from_datastore : après, chaque ligne est relue telle qu'elle est maintenant — un rendez-vous retiré le reste, un rendez-vous glissé reste où il a été lâché, les champs d'of_set_field et les rendez-vous ajoutés à la main restent. Rend 0 une fois posé, -5 quand le rôle n'est pas une des constantes ROLE_* ou quand la colonne n'est pas une de celles du DataStore du dernier of_from_datastore ; un nouveau ROLE_KEY donne à chaque ligne une nouvelle clé, et les handles des anciennes sont libérés, -2 quand le composant n'est pas créé

Ressources et catégories #

MéthodeRôle
of_add_resource (string as_key, string as_label)Ajoute une ressource — une personne, une salle, une machine ; sa couleur et sa visibilité passent par of_resource. Rend 0 une fois ajoutée, -5 quand la clé est vide, contient / ou `, ou est déjà prise, -2` quand le composant n'est pas créé
of_resource (string as_key)Le handle d'une ressource (n_pbt_scheduler_resource), créé au premier accès
of_remove_resource (string as_key)Retire une ressource ; ses rendez-vous restent — regroupés par ressource, dans la colonne (aucune). Rend 0 une fois retirée, -5 quand le calendrier n'a aucune ressource de cette clé, -2 quand le composant n'est pas créé
of_clear_resources ( )Retire toutes les ressources. Rend 0 une fois envoyé, -2 quand le composant n'est pas créé
of_add_category (string as_key, string as_label, long al_color)Ajoute une catégorie de couleur : les rendez-vous dont is_category la nomme prennent sa couleur (-1 = l'accent). Rend 0 une fois ajoutée, -5 quand la clé est vide, contient / ou `, ou est déjà prise, -2` quand le composant n'est pas créé
of_category (string as_key)Le handle d'une catégorie (n_pbt_scheduler_category), créé au premier accès
of_remove_category (string as_key)Retire une catégorie ; ses rendez-vous reviennent à l'accent. Rend 0 une fois retirée, -5 quand le calendrier n'a aucune catégorie de cette clé, -2 quand le composant n'est pas créé
of_clear_categories ( )Retire toutes les catégories. Rend 0 une fois envoyé, -2 quand le composant n'est pas créé
MéthodeRôle
of_next ( )Le jour, la semaine ou le mois suivant — la flèche de la barre d'outils. Rend 0 une fois envoyé, -2 quand le composant n'est pas créé
of_previous ( )Le jour, la semaine ou le mois précédent. Rend 0 une fois envoyé, -2 quand le composant n'est pas créé
of_go_to_today ( )Revient à aujourd'hui — le bouton Aujourd'hui. Rend 0 une fois envoyé, -2 quand le composant n'est pas créé
of_select_appointment (string as_key)Sélectionne un rendez-vous ("" = aucun), comme un clic : lève ue_selection_changed (rien s'il est déjà la sélection). Rend 0 une fois sélectionné, -5 quand le calendrier n'a aucun rendez-vous de cette clé, -2 quand le composant n'est pas créé
of_selected_key ( )La clé du rendez-vous sélectionné, "" quand aucun — lue en direct
of_show_appointment (string as_key)Amène un rendez-vous à l'écran : va à son jour, fait défiler jusqu'à son heure et le sélectionne, comme un clic : lève ue_selection_changed. Un jour que la semaine de travail ne montre pas (un samedi) fait passer la vue en semaine entière, et ue_view_changed le dit. Rend 0 une fois montré, -5 quand le calendrier n'a aucun rendez-vous de cette clé, -2 quand le composant n'est pas créé
of_scroll_to_time (string as_time)Fait défiler la grille horaire jusqu'à une heure, "hh:mm". Rend 0 une fois envoyé, -5 quand l'heure est vide, -2 quand le composant n'est pas créé
of_first_visible_date ( ) · of_last_visible_date ( )Le premier et le dernier jour que la vue montre, "yyyy-mm-dd" — lus en direct
of_shown_count ( )Rend le nombre de rendez-vous affichés dans la plage à l'écran : après is_filter, les masqués, les ressources masquées et le plafond du mode démo (les 12 premiers de cette plage) ; of_count compte tout le calendrier

Événements #

ÉvénementDéclenché quand
ue_appointment_clicked (string as_key)Un rendez-vous est cliqué (et sélectionné)
ue_appointment_opened (string as_key)Double-clic sur un rendez-vous, ou Entrée sur celui qui est sélectionné : ouvrez votre éditeur
ue_appointment_rclicked (string as_key, long al_x, long al_y)Clic droit sur un rendez-vous. al_x / al_y sont des pixels écran
ue_appointment_changing (string as_key, string as_start, string as_end, string as_resource)Avant qu'un déplacement ou un redimensionnement soit appliqué, seulement si ib_veto_changes est vrai. Rendez false pour remettre le rendez-vous où il était ; true par défaut
ue_appointment_moved (string as_key, string as_start, string as_end, string as_resource)L'utilisateur a glissé un rendez-vous : son nouveau début, sa nouvelle fin et sa ressource. Le calendrier le montre déjà là ; enregistrez-le (une ligne de DataStore : SetItem sur la ligne Long(as_key))
ue_appointment_resized (string as_key, string as_start, string as_end)L'utilisateur a tiré un bord d'un rendez-vous : son nouveau début et sa nouvelle fin
ue_range_selected (string as_start, string as_end, boolean ab_all_day, string as_resource)L'utilisateur a balayé des cases vides à la souris : la plage, pour y créer un rendez-vous. Balayée dans la bande « journée entière » ou dans le mois, ce sont des jours entiers : ab_all_day vaut true, dates seules, la dernière incluse
ue_new_requested (string as_start, string as_end, boolean ab_all_day, string as_resource)L'utilisateur demande un nouveau rendez-vous : double-clic sur une case ou un jour vide, ou le + d'un en-tête de jour (regroupé par ressource : d'un en-tête de ressource). Un jour entier arrive en dates seules, la fin incluse : deux fois la même date = un jour
ue_delete_requested (string as_key)Suppr a été pressée sur le rendez-vous sélectionné. Retirez-le (of_remove_appointment) une fois que votre application est d'accord
ue_slot_rclicked (string as_start, boolean ab_all_day, string as_resource, long al_x, long al_y)Clic droit sur une case ou un jour vide ; pour un jour, as_start est sa date seule. al_x / al_y sont des pixels écran
ue_selection_changed (string as_key)Le rendez-vous sélectionné a changé ("" = aucun) : un clic, ou of_select_appointment / of_show_appointment depuis votre code
ue_view_changed (string as_view)La vue a changé : l'utilisateur en a choisi une autre dans la barre d'outils ou a ouvert un jour par son « +N », votre code a posé is_view, ou of_show_appointment a fait passer la semaine de travail en semaine entière pour montrer un jour chômé
ue_date_changed (string as_first, string as_last)La plage visible a changé (navigation, vue, date) : son premier et son dernier jour, "yyyy-mm-dd", inclus. Levé aussi au premier affichage (sur la plage d'aujourd'hui), puis de nouveau quand votre code pose is_date ou is_view : une fenêtre qui les pose à l'ouverture en reçoit deux ; et après chaque of_reset, qui vide le calendrier : c'est une demande de données, pas un geste. C'est ici qu'on charge les rendez-vous de la plage
ue_ready ( )Le composant a fini de charger ; tout ce qui a été envoyé avant a été rejoué
ue_runtime_missing ( )Le runtime WebView2 est absent : le composant reste vide
ue_bg_color (long al_color)Le composant a calculé sa couleur de fond de thème ; l'userobject l'a déjà adoptée (backcolor)

Les modèles #

Ce qu'une carte, une ligne du mois et une info-bulle disent n'est pas figé : c'est un modèle que vous écrivez, en texte riche ([b], [br], [color=…], [symbol=…]…) avec des champs entre accolades. Quatre propriétés les portent : is_card_template (cartes des vues jour et semaine, agenda, barres du mois), is_month_template (une ligne de la vue mois), is_tooltip_title_template et is_tooltip_template (l'info-bulle). Le modèle d'info-bulle par défaut est :

[symbol=clock] {when}{?location}[br][symbol=location] {location}{/location}{?organizer}[br][symbol=person] {organizer}{/organizer}

La syntaxe #

ÉcritureEffet
{subject}La valeur du champ, échappée : un [ dans le sujet s'affiche, il n'ouvre pas de balise
{start:dddd d mmmm}Un champ date dans un format (jetons ci-dessous)
{?location}…{/location}Écrit le bloc seulement si le champ dit quelque chose qui n'est pas un NON : ni vide, ni 0, N, no ou false
{!all_day}…{/all_day}Écrit le bloc seulement si le champ est vide (ou faux)
{description:raw}Insère la valeur comme du balisage, sans l'échapper — pour un champ qui contient déjà des balises
{{ · }}Une accolade littérale

Les formats de date #

Les jetons sont ceux de PowerBuilder ; les noms de jours et de mois suivent la langue d'affichage. Un texte entre guillemets est écrit tel quel. Les mêmes jetons servent à is_time_format.

JetonÉcrit
yyyy · yyL'année, 2026 · 26
mmmm · mmmLe nom du mois, long · court
mm · mLe mois, 09 · 9 — ou les minutes juste après une heure, comme dans PowerBuilder
dddd · dddLe nom du jour, long · court
dd · dLe jour du mois, 05 · 5
hh · hL'heure, 09 · 9 (sur 12 heures avec AM/PM)
nn · nLes minutes, 05 · 5
AM/PM · am/pmLe repère du matin ou de l'après-midi

Les champs #

ChampValeur
key · subject · location · organizer · descriptionLa clé et les textes du rendez-vous
resource · resource_labelLa clé de sa ressource · son nom
category · category_labelLa clé de sa catégorie · son nom
status · status_labelLe statut (busy…) · son libellé, traduit dans la langue d'affichage
all_day · recurring · private · reminder · cancelledtrue, ou vide : faits pour {?…} et {!…}
start · endL'heure de début · de fin, au format is_time_format (vide pour une journée entière) ; avec un format, la date et l'heure — pour une journée entière, {end:…} est le dernier jour, comme is_end le relit
dateLe premier jour, en toutes lettres ; avec un format, le début formaté
time09:00-10:30, ou « Toute la journée »
whenLa phrase complète : jour, heures, et le jour de fin quand il diffère
duration45 min, 1 h 30, 2 days (traduit)
les vôtresTout champ posé par of_set_field, et toute colonne du DataStore d'of_from_datastore, sous son nom. Une valeur qui est une date accepte un format : {due_date:dd/mm}

Un champ inconnu écrit une chaîne vide.

Les symboles #

La balise [symbol=nom] du texte riche pose un symbole intégré, monochrome, dessiné dans la couleur du texte qui l'entoure — il suit le thème, le survol et la couleur de la carte, sans fichier à livrer : clock, location, person, people, calendar, repeat, lock, bell, phone, mail, video, note, tag, link, check, star, info, warning. Un nom inconnu s'affiche tel quel.


Ce que l'utilisateur peut faire sans une ligne de code #

Le calendrier ne crée, ne modifie ni ne supprime rien de lui-même au-delà du glisser : il demande, votre application décide. ib_read_only coupe tous ces gestes d'un coup, ib_read_only sur un rendez-vous les coupe pour lui seul.

Au clavier, une fois le calendrier atteint :

ToucheEffet
EntréeOuvre le rendez-vous sélectionné → ue_appointment_opened
SupprDemande la suppression du rendez-vous sélectionné → ue_delete_requested (rien si le calendrier ou le rendez-vous est en lecture seule)
Flèche haut / Flèche basSélectionne le rendez-vous précédent / suivant de la vue, dans l'ordre des heures de début → ue_selection_changed
Page haut / Page basLe jour, la semaine ou le mois précédent / suivant
Alt+DébutRevient à aujourd'hui
ÉchapAnnule un glisser en cours

Exemples #

Les rendez-vous d'un DataStore, et ce que l'utilisateur en fait #

Le DataStore ids_appts (variable d'instance) a les colonnes subject, start_date, end_date, location, room, category et customer. Les quatre premières jouent leur rôle par leur nom ; room le reçoit d'of_map.

// open event of the window : the appointments, retrieved the way your application already does
ids_appts = create datastore
ids_appts.dataobject = "d_appointments"
ids_appts.SetTransObject(SQLCA)
ids_appts.Retrieve()

// "room" is not a role name : say which role it plays, then load every row
uo_sched.of_map(/*role*/ u_pbt_scheduler.ROLE_RESOURCE, /*column*/ "room")
uo_sched.of_from_datastore(/*ads*/ ids_appts)
// ue_appointment_moved event of uo_sched : (string as_key, string as_start, string as_end, string as_resource)
// Local variables
long ll_row

// The key of a row loaded by of_from_datastore is its row number
ll_row = Long(as_key)
ids_appts.SetItem(ll_row, "start_date", DateTime(Date(Left(as_start, 10)), Time(Mid(as_start, 12))))
ids_appts.SetItem(ll_row, "end_date", DateTime(Date(Left(as_end, 10)), Time(Mid(as_end, 12))))
ids_appts.SetItem(ll_row, "room", as_resource)

// Save when YOUR application decides : here, at once
ids_appts.Update()
// ue_appointment_resized event of uo_sched : (string as_key, string as_start, string as_end)
// Local variables
long ll_row

// Only the times change : same row, same two columns
ll_row = Long(as_key)
ids_appts.SetItem(ll_row, "start_date", DateTime(Date(Left(as_start, 10)), Time(Mid(as_start, 12))))
ids_appts.SetItem(ll_row, "end_date", DateTime(Date(Left(as_end, 10)), Time(Mid(as_end, 12))))
ids_appts.Update()

Créer et supprimer #

// ue_new_requested event of uo_sched : (string as_start, string as_end, boolean ab_all_day, string as_resource)
// Local variables
long ll_row

// A new row, prefilled with the slot the user chose
ll_row = ids_appts.InsertRow(0)
ids_appts.SetItem(ll_row, "subject", "New appointment")
ids_appts.SetItem(ll_row, "start_date", DateTime(Date(Left(as_start, 10)), Time(Mid(as_start, 12))))
ids_appts.SetItem(ll_row, "end_date", DateTime(Date(Left(as_end, 10)), Time(Mid(as_end, 12))))
ids_appts.SetItem(ll_row, "room", as_resource)

// Reload (the row numbers are the keys), then bring the new one into view
uo_sched.of_from_datastore(/*ads*/ ids_appts)
uo_sched.of_show_appointment(/*key*/ String(ll_row))
// ue_delete_requested event of uo_sched : (string as_key)
// Ask first : the calendar never deletes by itself
if MessageBox("Delete", "Delete this appointment?", Question!, YesNo!) = 2 then return
ids_appts.DeleteRow(Long(as_key))
ids_appts.Update()

// The rows after it changed number : reload
uo_sched.of_from_datastore(/*ads*/ ids_appts)

Une colonne par salle #

// The rooms, each with its own colour, side by side under each day
uo_sched.of_set_redraw(/*on*/ false)
uo_sched.of_add_resource(/*key*/ "r1", /*label*/ "Room A")
uo_sched.of_add_resource(/*key*/ "r2", /*label*/ "Room B")
uo_sched.of_resource(/*key*/ "r1").il_color = RGB(15, 108, 189)
uo_sched.of_resource(/*key*/ "r2").il_color = RGB(31, 158, 117)
uo_sched.is_group_by = u_pbt_scheduler.GROUP_RESOURCE
uo_sched.is_view = u_pbt_scheduler.VIEW_DAY

// Each appointment names its room
uo_sched.of_add_appointment(/*key*/ "k1", /*subject*/ "Kickoff", /*start*/ "2026-09-22 09:00", /*end*/ "2026-09-22 10:00")
uo_sched.of_appointment(/*key*/ "k1").is_resource = "r1"
uo_sched.of_add_appointment(/*key*/ "k2", /*subject*/ "Interview", /*start*/ "2026-09-22 10:30", /*end*/ "2026-09-22 11:30")
uo_sched.of_appointment(/*key*/ "k2").is_resource = "r2"
uo_sched.of_set_redraw(/*on*/ true)
// A checkbox of the window hides Room B and its appointments, like unticking a calendar in Outlook
uo_sched.of_resource(/*key*/ "r2").ib_visible = cbx_room_b.checked

Des cartes et des info-bulles à vous #

// The card : the time, the subject in bold, the customer (a DataStore column) when there is one
uo_sched.is_card_template = "{start} [b]{subject}[/b]{?customer}[br][symbol=people] {customer}{/customer}"

// The month line : a small lock on the private ones
uo_sched.is_month_template = "{?private}[symbol=lock] {/private}{subject}"

// The tooltip : the date written out, the duration, the status
uo_sched.is_tooltip_title_template = "{subject}"
uo_sched.is_tooltip_template = "[symbol=calendar] {start:dddd d mmmm}, {time} ({duration})[br][symbol=info] {status_label}"

Refuser un déplacement #

// Ask before any move or resize is applied
uo_sched.ib_veto_changes = true
// ue_appointment_changing event of uo_sched : (string as_key, string as_start, string as_end, string as_resource) returns boolean
// Nothing on a Saturday or a Sunday : returning false puts the appointment back
if DayNumber(Date(Left(as_start, 10))) = 1 or DayNumber(Date(Left(as_start, 10))) = 7 then return false
return true

Ne charger que ce qui se voit #

Sur des années d'historique, inutile de tout lire : ue_date_changed donne la plage à l'écran à chaque navigation, et au premier affichage. Ici d_appointments prend deux arguments datetime, début et fin de la plage.

// ue_date_changed event of uo_sched : (string as_first, string as_last)
// The last day is INCLUDED : read up to the start of the day after
ids_appts.Retrieve(DateTime(Date(as_first)), DateTime(RelativeDate(Date(as_last), 1)))
uo_sched.of_from_datastore(/*ads*/ ids_appts)

Votre menu sur un rendez-vous #

// ue_appointment_rclicked event of uo_sched : (string as_key, long al_x, long al_y)
// Local variables
m_appointment lm_menu

// Remember which appointment the menu is about, then open YOUR menu under the pointer
is_menu_key = as_key
lm_menu = create m_appointment
lm_menu.m_popup.PopMenu(parent.PointerX(), parent.PointerY())
destroy lm_menu

Bonnes pratiques #

Limites de la 4.0 #

Ce que le calendrier ne fait pas — à savoir avant de le choisir :

Hérité du socle commun #

Ces membres existent sur tous les composants visuels — ils ne sont pas propres à celui-ci. Ils sont détaillés une seule fois, dans les chapitres transverses ; cette table dit seulement où les lire.

MembresRôleDétaillé dans
of_count · of_keys_at · of_hasParcourir ce que le composant contient3.2 Les items
of_resetRemettre le composant à zéro3.6 Remettre un composant à zéro : of_reset()
of_register_shortcut · of_clear_shortcutsRaccourcis clavier du composant3.5 Les raccourcis clavier
of_is_created · of_is_ready · of_get_last_errorS'il est né, s'il est prêt, ce qui a échoué3.7 Diagnostic
of_save_as_png · of_save_as_jpgExporter le rendu en image3.8 Exporter le rendu en image
of_set_redrawGrouper les modifications en un seul repaint3.10 Bonnes pratiques
of_preload_iconsIcônes affichées sans délaiAffichage instantané : of_icon
of_set_translationTraduire un libellé du composant5.2 Adapter un libellé : of_set_translation
of_focus_webviewDonner le focus au composant6.4 Clavier et focus
of_print · of_print_to_pdfImprimer, ou écrire un PDF6.9 Imprimer
of_set_property · of_get_property · of_component_namePiloter une propriété par son nom3.1 Le moteur de propriétés

Deux aides ne sont pas héritées : of_icon et of_escape_markup vivent sur n_pbt_utils. Déclarez-en une — n_pbt_utils lnv_utils, rien à créer — et appelez-les dessus.

← Référence des composants · Sommaire du guide