scheduler — u_pbt_scheduler #
← Referencia de componentes · Índice de la guía
Un calendario al estilo de Outlook: vistas día, semana laboral, semana, mes y agenda, banda « todo el día », arrastrar y soltar para mover y redimensionar, recursos uno al lado del otro, categorías de color, y tarjetas e información sobre herramientas escritas por plantillas. Se llena cita a cita, o con una sola llamada desde un DataStore — y cada gesto del usuario le devuelve la fila que hay que actualizar.
▶ Verlo en vivo — Aplicación de demostración, mosaico Scheduler: la vista previa, el código que lo genera y esta página, uno al lado del otro.
De un vistazo #
| Userobject | u_pbt_scheduler |
| Clases de items | n_pbt_scheduler_appointment (una cita, of_appointment) · n_pbt_scheduler_resource (un recurso, of_resource) · n_pbt_scheduler_category (una categoría, of_category) |
| Sirve para | Planificación de un equipo, reserva de salas o máquinas, agenda de un comercial, citas de pacientes — todo lo que se coloca sobre días y horas |
| Límite en modo demo | Las 12 primeras citas del intervalo en pantalla, por hora de inicio; las demás se quedan en memoria sin mostrarse — véase el modo demo |
Inicio rápido #
// 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)
Entender el calendario #
Las vistas #
is_view elige la vista, is_date el día alrededor del cual se construye: su semana, su mes. El usuario cambia una y otro desde la barra de herramientas del componente (Hoy, anterior, siguiente, menú de vistas) — las dos propiedades se releen en directo, y ue_view_changed / ue_date_changed lo indican, venga el cambio del usuario o de su código.
| Vista | Qué muestra |
|---|---|
VIEW_DAY | Un día sobre una cuadrícula horaria |
VIEW_WORK_WEEK | Los días laborables de la semana (is_work_days) — la vista predeterminada |
VIEW_WEEK | Los siete días, a partir de ii_first_day_of_week |
VIEW_MONTH | Seis semanas; una cita de varios días se extiende como una barra sobre sus días |
VIEW_AGENDA | Una lista, día a día, sobre ii_agenda_days días |
Las fechas #
Una fecha viaja como texto, "yyyy-mm-dd hh:mm" — en los métodos, las propiedades y los eventos. Es una hora local flotante: sin zona horaria ni horario de verano; "2026-09-22 09:00" se muestra a las 09:00, en todos los equipos.
- El fin es exclusivo. Una cita de 09:00 a 10:00 termina a las 10:00: la siguiente, que empieza a las 10:00, no se solapa con ella. Sin fin, una cita dura 30 minutos.
- Una fecha sin hora incluye sus dos días.
"2026-09-24"→"2026-09-25"conib_all_day = truees el 24 y el 25. Para una cita de todo el día se ignora la hora: una columna datetime de DataWindow, que lleva00:00:00, da días, el último incluido. - Lo que el calendario acepta también:
"2026-09-22T09:30", segundos, y el texto de una columna datetime de DataWindow.of_add_appointmenttiene una sobrecarga que recibe dosdatetime. - Lo que devuelven los eventos: las fechas en la forma en que las escribió —
"yyyy-mm-dd hh:mm", fin exclusivo, para una cita con hora; solo fechas, ambos días incluidos, para una cita de todo el día. Es también lo queis_starteis_endreleen en el handle.
// 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 banda « todo el día » #
Encima de la cuadrícula horaria de las vistas día y semana, una banda recibe las citas ib_all_day y las que duran 24 horas o más: un seminario de tres días cabe allí en una barra en lugar de aplastar tres columnas. ib_all_day_band = false la retira. En la vista mes, esas citas son barras que atraviesan sus días; las demás, una línea escrita por is_month_template.
Las citas de un DataStore #
of_from_datastore(ids) carga el calendario con una sola llamada: una fila = una cita, y su clave es su número de fila — es la que cada evento le devuelve, lista para SetItem. Una columna desempeña un rol cuando lleva su nombre, o cuando of_map se lo asigna:
| Rol | Nombres reconocidos sin of_map |
|---|---|
ROLE_SUBJECT | subject, title |
ROLE_START · ROLE_END | start, start_date, starts · end, end_date, ends |
ROLE_ALL_DAY · ROLE_READ_ONLY | all_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_CANCELLED | el nombre del rol: key, location, organizer, description, resource, category, status, recurring, private, reminder, cancelled |
- Una columna booleana es verdadera para
1,true,Yoyes. Una columnastatuslleva los valores deSTATUS_*(busy,tentative,free,oof,elsewhere). Cada nombre se reconoce también con el prefijois_: is_private, ya queprivatees una palabra reservada de PowerScript. - Todas las columnas, con rol o sin él, son campos de las plantillas: una columna
customerse escribe{customer}en la tarjeta, y se lee conof_get_field. - Una columna que desempeña
ROLE_KEYsustituye al número de fila como clave: resérvela para datos que no vuelve a cargar desde ese DataStore. Sus valores deben ser únicos y no vacíos: una fila que no lo cumple (o cuyo valor contiene/o|) conserva su número de fila como clave, yue_script_errorlo indica una vez. - El calendario nunca modifica el DataStore: le dice lo que hizo el usuario (
ue_appointment_moved,ue_appointment_resized), usted haceSetItem, y luegoUpdate()cuando su aplicación lo decide. - Después de un
InsertRow, unDeleteRow, unSorto unFilter, los números de fila cambian: vuelva a llamar aof_from_datastore.
Recursos y agrupación #
Un recurso es lo que se reserva: una persona, una sala, una máquina (of_add_resource). Una cita lo nombra mediante is_resource. Con is_group_by = GROUP_RESOURCE, cada día de las vistas día y semana se divide en una columna por recurso, y arrastrar una tarjeta a otra columna cambia su recurso — ue_appointment_moved lo devuelve en as_resource. ib_visible = false en un recurso oculta su columna y sus citas, como desmarcar un calendario en Outlook.
Colores, categorías y estado #
El color de una tarjeta se decide en este orden: el il_accent establecido en esta cita, luego el color de su categoría (of_add_category, is_category), luego el de su recurso, luego el acento del tema. El filete de la izquierda indica el estado (is_status, el « Mostrar como » de Outlook: ocupado, provisional, libre, fuera de la oficina, en otro lugar); una cita ib_cancelled se dibuja hueca, y ib_recurring, ib_private, ib_reminder ponen un pequeño signo en la tarjeta.
Propiedades #
| Propiedad | Tipo | Predeterminado | Función |
|---|---|---|---|
is_view | string | VIEW_WORK_WEEK | La vista mostrada (VIEW_*). Releída en directo: el usuario la cambia desde la barra de herramientas. Fijarla emite ue_view_changed, como el menú de vistas (nada si la vista no cambia) |
is_date | string | hoy | El día mostrado, "yyyy-mm-dd": la vista se construye a su alrededor (su semana, su mes). Releído en directo: las flechas lo desplazan. Una vez fijado, is_now ya no lo desplaza; "" devuelve la vista a hoy |
is_now | string | "" | « Ahora », para la línea de la hora actual y el botón Hoy: "" = el reloj del equipo; "yyyy-mm-dd hh:mm" lo fija (demostración, prueba, reproducción). Mientras is_date no se haya fijado nunca, la vista va a su día |
ii_first_day_of_week | integer | 1 | Primer día de la semana, en números ISO como is_work_days: 1 = lunes … 7 = domingo; 0 se acepta para domingo |
is_work_days | string | "1|2|3|4|5" | Los días laborables, números ISO unidos por | (1 = lunes … 7 = domingo, 0 aceptado para domingo): forman la semana laboral, los demás se sombrean |
is_work_start · is_work_end | string | "08:00" · "17:00" | El horario de trabajo, "hh:mm": el resto del día se sombrea |
is_day_start · is_day_end | string | "00:00" · "24:00" | Las horas que muestra la cuadrícula horaria; lo que queda fuera se cuenta en el borde de su columna (« ▲ 1 antes », « ▼ 1 después »), con lo que el desplazamiento oculta por encima o por debajo de la vista; un clic en la marca trae a la vista la cita oculta más cercana |
ii_slot_minutes | integer | 30 | El paso de la cuadrícula en minutos: 5, 10, 15, 20, 30 o 60. Un arrastre se ajusta a él |
ii_hour_height | integer | 48 | La altura de una hora, en píxeles |
is_scroll_time | string | "08:00" | La hora a la que se desplaza la cuadrícula al abrir una vista |
ib_show_now | boolean | true | La línea roja de la hora actual |
ib_toolbar | boolean | true | La barra de herramientas: Hoy, anterior, siguiente, el título, el menú de vistas |
ib_week_numbers | boolean | false | Los números de semana ISO, en la esquina de la cuadrícula horaria y delante de cada fila del mes |
ib_read_only | boolean | false | Nada se mueve, se redimensiona ni se crea con el ratón; Supr ya no pide nada |
ib_all_day_band | boolean | true | La banda « todo el día » encima de la cuadrícula horaria |
ib_tooltips | boolean | true | La información sobre herramientas de cada cita, escrita por las plantillas de información |
ib_veto_changes | boolean | false | Pregunta antes de aplicar un desplazamiento o un redimensionamiento: emite ue_appointment_changing, que puede rechazar |
is_card_template | string | "[b]{subject}[/b]{?location}; {location}{/location}" | La plantilla de la tarjeta: vistas día y semana, agenda, barras del mes — véase Las plantillas |
is_month_template | string | "{!all_day}{start} {/all_day}{subject}" | Una línea de la vista mes, para una cita contenida en un día |
is_tooltip_title_template | string | "{subject}" | El título de la información sobre herramientas de una cita |
is_tooltip_template | string | la hora, el lugar, el organizador | El texto de la información sobre herramientas de una cita — véase Las plantillas |
is_group_by | string | GROUP_NONE | GROUP_RESOURCE: una columna por recurso bajo cada día, más una columna (ninguno) al final cuando una cita no tiene un recurso conocido por el calendario |
is_filter | string | "" | Muestra solo las citas que contienen este texto (asunto, lugar, organizador, descripción, campos); "" las muestra todas |
is_time_format | string | "hh:mm" | Cómo se escribe una hora: "hh:mm", "h:mm AM/PM"… (símbolos de Las plantillas) |
ii_agenda_days | integer | 7 | Cuántos días lista la vista agenda |
is_theme_style | string | "" | Estilo visual del componente (constantes THEME_STYLE_*); vacío = el de la aplicación, seguido en cada cambio |
is_theme_mode | string | "" | Variante clara u oscura (constantes THEME_MODE_*); vacío = la de la aplicación, seguida en cada cambio |
il_theme_accent | long | -1 | Color de acento de este componente (-1 = acento de la aplicación, o el del tema) |
is_tooltip | string | "" | Información sobre herramientas simple del componente (una cita tiene la suya, escrita por las plantillas) |
is_super_tooltip_title | string | "" | Título de la información enriquecida (tiene prioridad sobre is_tooltip) |
is_super_tooltip_text | string | "" | Texto de la información enriquecida (se admite el marcado enriquecido) |
is_super_tooltip_image | string | "" | Imagen de la información enriquecida |
Propiedades de una cita #
Una cita se controla mediante su handle, of_appointment("clave") — creado en el primer acceso, sigue siendo válido después. Una propiedad leída pregunta al componente cuánto vale ahora: tras un arrastre, is_start e is_end ya dicen dónde la soltó el usuario.
// A handle used once fits on one line
uo_sched.of_appointment(/*key*/ "a1").is_status = n_pbt_scheduler_appointment.STATUS_TENTATIVE
| Propiedad | Tipo | Predeterminado | Función |
|---|---|---|---|
is_subject | string | el de of_add_appointment | El asunto, lo que la tarjeta muestra primero ({subject}) |
is_start · is_end | string | los de of_add_appointment | Inicio y fin, "yyyy-mm-dd hh:mm", fin exclusivo; para una cita de todo el día, fechas "yyyy-mm-dd", ambos días incluidos. Cualquier otra escritura (22/09/2026 09:00) se guarda pero nunca se dibuja |
ib_all_day | boolean | false | Ocupa días enteros: se dibuja en la banda « todo el día » |
is_location · is_organizer · is_description | string | "" | El lugar ({location}), el organizador ({organizer}), un texto más largo ({description}) |
is_resource | string | "" | La clave de su recurso: su columna cuando el calendario agrupa por recurso, su color cuando no tiene categoría |
is_category | string | "" | La clave de su categoría: el color de la tarjeta |
is_status | string | STATUS_BUSY | El « Mostrar como » de Outlook (STATUS_*), dibujado por el filete de la izquierda |
ib_recurring · ib_private · ib_reminder | boolean | false | Pequeños signos en la tarjeta: una periodicidad, una cita privada, un recordatorio |
ib_cancelled | boolean | false | Una cita cancelada se dibuja hueca |
ib_read_only | boolean | false | El usuario no puede ni moverla, ni redimensionarla, ni pedir su eliminación |
ib_visible | boolean | true | La oculta sin retirarla |
Como todo item, una cita lleva también la información sobre herramientas común (is_tooltip, is_super_tooltip_title, is_super_tooltip_text, is_super_tooltip_image) — que entonces sustituye a la de las plantillas — y los colores de item: il_accent vuelve a colorear la tarjeta y su filete, il_back_color, il_text_color, il_back_color_hover e il_text_color_hover la pintan en reposo y al pasar el ratón.
Propiedades de un recurso y de una categoría #
| Propiedad | Handle | Función |
|---|---|---|
is_label | n_pbt_scheduler_resource | El nombre mostrado encima de su columna cuando el calendario agrupa por recurso ({resource_label}) |
il_color | n_pbt_scheduler_resource | El color de sus citas que no tienen categoría; -1 = el acento |
ib_visible | n_pbt_scheduler_resource | false oculta su columna y sus citas |
is_label | n_pbt_scheduler_category | Su nombre ({category_label}) |
il_color | n_pbt_scheduler_category | El color de sus citas; -1 = el acento. Una categoría no se dibuja por sí misma: el tooltip y los cinco colores de elemento que hereda se guardan y se releen, sin efecto visible |
Constantes #
| Familia | Constantes | Llevadas por |
|---|---|---|
| Vista | VIEW_DAY, VIEW_WORK_WEEK, VIEW_WEEK, VIEW_MONTH, VIEW_AGENDA | el componente (is_view) |
| Agrupación | GROUP_NONE, GROUP_RESOURCE | el componente (is_group_by) |
| Rol de una columna | ROLE_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_ONLY | el componente (of_map) |
| Estado | STATUS_BUSY, STATUS_TENTATIVE, STATUS_FREE, STATUS_OOF, STATUS_ELSEWHERE | el handle de cita (is_status) |
Las constantes se leen en el objeto que las lleva:
u_pbt_scheduler.VIEW_MONTHpara una propiedad del componente,n_pbt_scheduler_appointment.STATUS_OOFpara una propiedad de cita.
Métodos #
Citas #
| Método | Función | |
|---|---|---|
of_add_appointment (string as_key, string as_subject, string as_start, string as_end) | Añade una cita: su clave (única), su asunto, su inicio y su fin "yyyy-mm-dd hh:mm". Todo lo demás pasa por su handle. Devuelve 0 una vez añadida, -5 cuando la clave está vacía, contiene / o ` | , o **ya está ocupada** (una cita no se actualiza así: lo hace su handle), o cuando el inicio — o un fin indicado — no está escrito yyyy-mm-dd o yyyy-mm-dd hh:mm (String(ldt) escribe 22/09/2026 en un equipo francés: use la sobrecarga datetime), -2` cuando el componente no está creado |
of_add_appointment (string as_key, string as_subject, datetime adt_start, datetime adt_end) | Lo mismo, a partir de dos datetime; un fin nulo equivale al inicio. Para un día entero, el fin es el último día mismo, incluido: dos veces la misma fecha = un día. Devuelve 0 una vez añadida, -5 cuando la clave está vacía, contiene / o ` | o ya está ocupada, o cuando el inicio es nulo, -2` cuando el componente no está creado |
of_appointment (string as_key) | El handle de una cita (n_pbt_scheduler_appointment), creado en el primer acceso — véase Propiedades de una cita | |
of_remove_appointment (string as_key) | Retira una cita. Devuelve 0 una vez retirada, -5 cuando el calendario no tiene ninguna cita con esta clave, -2 cuando el componente no está creado | |
of_clear_appointments ( ) | Retira todas las citas; los recursos, categorías y opciones se mantienen. Devuelve 0 una vez enviado, -2 cuando el componente no está creado | |
of_set_field (string as_key, string as_field, string as_value) | Da a una cita un campo propio, para las plantillas: tras of_set_field("a1", "customer", "ACME"), {customer} escribe ACME en su tarjeta. Devuelve 0 una vez establecido, -5 cuando el campo está vacío o el calendario no tiene ninguna cita con esta clave, -2 cuando el componente no está creado | |
of_get_field (string as_key, string as_field) | Lee en directo un campo de una cita: uno de los suyos (of_set_field) o una columna del DataStore del que procede; "" cuando no lo tiene |
DataStore #
| Método | Función |
|---|---|
of_from_datastore (datastore ads) | El puente DataStore: una fila = una cita, su clave = su número de fila, cada columna = un campo de las plantillas. Sustituye las citas mostradas. Devuelve 0 una vez cargado, -5 cuando el DataStore no es válido o no tiene ninguna columna, -2 cuando el componente no está creado |
of_map (string as_role, string as_column) | Da un rol (ROLE_*) a una columna cuyo nombre no lo dice: of_map(ROLE_SUBJECT, "title_text"). Antes o después de of_from_datastore: después, cada fila se vuelve a leer tal como está ahora — una cita retirada sigue retirada, una arrastrada se queda donde se soltó, los campos de of_set_field y las citas añadidas a mano se mantienen. Devuelve 0 una vez establecido, -5 cuando el rol no es una de las constantes ROLE_* o cuando la columna no es una de las del DataStore del último of_from_datastore; un nuevo ROLE_KEY da a cada fila una nueva clave, y los handles de las antiguas se liberan, -2 cuando el componente no está creado |
Recursos y categorías #
| Método | Función | |
|---|---|---|
of_add_resource (string as_key, string as_label) | Añade un recurso — una persona, una sala, una máquina; su color y su visibilidad pasan por of_resource. Devuelve 0 una vez añadido, -5 cuando la clave está vacía, contiene / o ` | , o ya está ocupada, -2` cuando el componente no está creado |
of_resource (string as_key) | El handle de un recurso (n_pbt_scheduler_resource), creado en el primer acceso | |
of_remove_resource (string as_key) | Retira un recurso; sus citas se mantienen — agrupadas por recurso, en la columna (ninguno). Devuelve 0 una vez retirado, -5 cuando el calendario no tiene ningún recurso con esta clave, -2 cuando el componente no está creado | |
of_clear_resources ( ) | Retira todos los recursos. Devuelve 0 una vez enviado, -2 cuando el componente no está creado | |
of_add_category (string as_key, string as_label, long al_color) | Añade una categoría de color: las citas cuyo is_category la nombra toman su color (-1 = el acento). Devuelve 0 una vez añadida, -5 cuando la clave está vacía, contiene / o ` | , o ya está ocupada, -2` cuando el componente no está creado |
of_category (string as_key) | El handle de una categoría (n_pbt_scheduler_category), creado en el primer acceso | |
of_remove_category (string as_key) | Retira una categoría; sus citas vuelven al acento. Devuelve 0 una vez retirada, -5 cuando el calendario no tiene ninguna categoría con esta clave, -2 cuando el componente no está creado | |
of_clear_categories ( ) | Retira todas las categorías. Devuelve 0 una vez enviado, -2 cuando el componente no está creado |
Navegación y selección #
| Método | Función |
|---|---|
of_next ( ) | El día, la semana o el mes siguiente — la flecha de la barra de herramientas. Devuelve 0 una vez enviado, -2 cuando el componente no está creado |
of_previous ( ) | El día, la semana o el mes anterior. Devuelve 0 una vez enviado, -2 cuando el componente no está creado |
of_go_to_today ( ) | Vuelve a hoy — el botón Hoy. Devuelve 0 una vez enviado, -2 cuando el componente no está creado |
of_select_appointment (string as_key) | Selecciona una cita ("" = ninguna), como lo haría un clic: emite ue_selection_changed (nada si ya es la selección). Devuelve 0 una vez seleccionada, -5 cuando el calendario no tiene ninguna cita con esta clave, -2 cuando el componente no está creado |
of_selected_key ( ) | La clave de la cita seleccionada, "" cuando no hay ninguna — leída en directo |
of_show_appointment (string as_key) | Lleva una cita a la vista: va a su día, se desplaza hasta su hora y la selecciona, como un clic: emite ue_selection_changed. Un día que la semana laboral no muestra (un sábado) pasa la vista a la semana completa, y ue_view_changed lo indica. Devuelve 0 una vez mostrada, -5 cuando el calendario no tiene ninguna cita con esta clave, -2 cuando el componente no está creado |
of_scroll_to_time (string as_time) | Desplaza la cuadrícula horaria hasta una hora, "hh:mm". Devuelve 0 una vez enviado, -5 cuando la hora está vacía, -2 cuando el componente no está creado |
of_first_visible_date ( ) · of_last_visible_date ( ) | El primer y el último día que muestra la vista, "yyyy-mm-dd" — leídos en directo |
of_shown_count ( ) | Devuelve el número de citas mostradas en el intervalo en pantalla: tras is_filter, las ocultas, los recursos ocultos y el límite del modo demo (las 12 primeras de ese intervalo); of_count cuenta todo el calendario |
Eventos #
| Evento | Se emite cuando |
|---|---|
ue_appointment_clicked (string as_key) | Se hizo clic en una cita (y quedó seleccionada) |
ue_appointment_opened (string as_key) | Doble clic en una cita, o Intro sobre la seleccionada: abra su editor |
ue_appointment_rclicked (string as_key, long al_x, long al_y) | Clic derecho en una cita. al_x / al_y son píxeles de pantalla |
ue_appointment_changing (string as_key, string as_start, string as_end, string as_resource) | Antes de aplicar un desplazamiento o un redimensionamiento, solo si ib_veto_changes es verdadero. Devuelva false para devolver la cita a donde estaba; true de forma predeterminada |
ue_appointment_moved (string as_key, string as_start, string as_end, string as_resource) | El usuario arrastró una cita: su nuevo inicio, su nuevo fin y su recurso. El calendario ya la muestra ahí; guárdela (una fila de DataStore: SetItem en la fila Long(as_key)) |
ue_appointment_resized (string as_key, string as_start, string as_end) | El usuario arrastró un borde de una cita: su nuevo inicio y su nuevo fin |
ue_range_selected (string as_start, string as_end, boolean ab_all_day, string as_resource) | El usuario barrió casillas vacías con el ratón: el intervalo, para crear una cita en él. Barrido en la banda « todo el día » o en la vista mes, son días enteros: ab_all_day vale true, solo fechas, la última incluida |
ue_new_requested (string as_start, string as_end, boolean ab_all_day, string as_resource) | El usuario pide una nueva cita: doble clic en una casilla o un día vacío, o el + de un encabezado de día (agrupado por recurso: de un encabezado de recurso). Un día entero llega como fechas solas, el fin incluido: dos veces la misma fecha = un día |
ue_delete_requested (string as_key) | Se pulsó Supr sobre la cita seleccionada. Retírela (of_remove_appointment) una vez que su aplicación esté de acuerdo |
ue_slot_rclicked (string as_start, boolean ab_all_day, string as_resource, long al_x, long al_y) | Clic derecho en una casilla o un día vacío; para un día, as_start es solo su fecha. al_x / al_y son píxeles de pantalla |
ue_selection_changed (string as_key) | La cita seleccionada cambió ("" = ninguna): un clic, o of_select_appointment / of_show_appointment desde su código |
ue_view_changed (string as_view) | La vista cambió: el usuario eligió otra en la barra de herramientas o abrió un día con su « +N », su código fijó is_view, o of_show_appointment pasó la semana laboral a la semana completa para mostrar un día no laborable |
ue_date_changed (string as_first, string as_last) | El intervalo visible cambió (navegación, vista, fecha): su primer y último día, "yyyy-mm-dd", incluidos. Se emite también en la primera visualización (sobre el intervalo de hoy), y de nuevo cuando su código fija is_date o is_view: una ventana que los fija al abrirse recibe dos; y tras cada of_reset, que vacía el calendario: es una petición de datos, no un gesto. Es aquí donde se cargan las citas del intervalo |
ue_ready ( ) | El componente terminó de cargarse; todo lo enviado antes se ha reproducido |
ue_runtime_missing ( ) | Falta el runtime WebView2: el componente permanece vacío |
ue_bg_color (long al_color) | El componente calculó su color de fondo del tema; el userobject ya lo ha adoptado (backcolor) |
Las plantillas #
Lo que dicen una tarjeta, una línea del mes y una información sobre herramientas no es fijo: es una plantilla que usted escribe, en texto enriquecido ([b], [br], [color=…], [symbol=…]…) con campos entre llaves. Cuatro propiedades las llevan: is_card_template (tarjetas de las vistas día y semana, agenda, barras del mes), is_month_template (una línea de la vista mes), is_tooltip_title_template e is_tooltip_template (la información sobre herramientas). La plantilla de información predeterminada es:
[symbol=clock] {when}{?location}[br][symbol=location] {location}{/location}{?organizer}[br][symbol=person] {organizer}{/organizer}
La sintaxis #
| Escritura | Efecto |
|---|---|
{subject} | El valor del campo, escapado: un [ en el asunto se muestra, no abre una etiqueta |
{start:dddd d mmmm} | Un campo de fecha en un formato (símbolos abajo) |
{?location}…{/location} | Escribe el bloque solo si el campo dice algo que no es un NO: ni vacío, ni 0, N, no o false |
{!all_day}…{/all_day} | Escribe el bloque solo si el campo está vacío (o es falso) |
{description:raw} | Inserta el valor como marcado, sin escaparlo — para un campo que ya contiene etiquetas |
{{ · }} | Una llave literal |
Los formatos de fecha #
Los símbolos son los de PowerBuilder; los nombres de días y meses siguen el idioma de visualización. Un texto entre comillas se escribe tal cual. Los mismos símbolos sirven para is_time_format.
| Símbolo | Escribe |
|---|---|
yyyy · yy | El año, 2026 · 26 |
mmmm · mmm | El nombre del mes, largo · corto |
mm · m | El mes, 09 · 9 — o los minutos justo después de una hora, como en PowerBuilder |
dddd · ddd | El nombre del día, largo · corto |
dd · d | El día del mes, 05 · 5 |
hh · h | La hora, 09 · 9 (en 12 horas con AM/PM) |
nn · n | Los minutos, 05 · 5 |
AM/PM · am/pm | La marca de la mañana o de la tarde |
Los campos #
| Campo | Valor |
|---|---|
key · subject · location · organizer · description | La clave y los textos de la cita |
resource · resource_label | La clave de su recurso · su nombre |
category · category_label | La clave de su categoría · su nombre |
status · status_label | El estado (busy…) · su etiqueta, traducida al idioma de visualización |
all_day · recurring · private · reminder · cancelled | true, o vacío: pensados para {?…} y {!…} |
start · end | La hora de inicio · de fin, en el formato is_time_format (vacía para una cita de todo el día); con un formato, la fecha y la hora — para una cita de todo el día, {end:…} es el último día, como lo relee is_end |
date | El primer día, escrito completo; con un formato, el inicio formateado |
time | 09:00-10:30, o « Todo el día » |
when | La frase completa: día, horas, y el día de fin cuando difiere |
duration | 45 min, 1 h 30, 2 days (traducido) |
| los suyos | Todo campo establecido por of_set_field, y toda columna del DataStore de of_from_datastore, con su nombre. Un valor que es una fecha acepta un formato: {due_date:dd/mm} |
Un campo desconocido escribe una cadena vacía.
Los símbolos #
La etiqueta de texto enriquecido [symbol=nombre] coloca un símbolo integrado, monocromo, dibujado en el color del texto que lo rodea — sigue el tema, el paso del ratón y el color de la tarjeta, sin archivo que distribuir: clock, location, person, people, calendar, repeat, lock, bell, phone, mail, video, note, tag, link, check, star, info, warning. Un nombre desconocido se muestra tal cual.
Lo que el usuario puede hacer sin una línea de código #
- navegar: Hoy, anterior, siguiente, y el menú de vistas de la barra de herramientas;
- mover una cita a otra hora, otro día u otro recurso, arrastrándola — el paso sigue
ii_slot_minutes; - redimensionar una cita arrastrando su borde;
- barrer casillas vacías para elegir un intervalo →
ue_range_selected— en la banda « todo el día » o en la vista mes, días enteros; - pedir una cita con un doble clic en una casilla vacía o con el + de un encabezado de día (de un encabezado de recurso cuando el calendario está agrupado) →
ue_new_requested; - abrir una cita con un doble clic →
ue_appointment_opened, y hacer clic derecho en una cita o una casilla vacía para su menú.
El calendario no crea, no modifica ni elimina nada por sí mismo más allá del arrastre: pregunta, su aplicación decide. ib_read_only desactiva todos estos gestos de una vez, ib_read_only en una cita los desactiva solo para ella.
Con el teclado, una vez que el calendario tiene el foco:
| Tecla | Efecto |
|---|---|
| Intro | Abre la cita seleccionada → ue_appointment_opened |
| Supr | Pide la eliminación de la cita seleccionada → ue_delete_requested (nada si el calendario o la cita es de solo lectura) |
| Flecha arriba / Flecha abajo | Selecciona la cita anterior / siguiente de la vista, en el orden de su hora de inicio → ue_selection_changed |
| Re Pág / Av Pág | El día, la semana o el mes anterior / siguiente |
| Alt+Inicio | Vuelve a hoy |
| Esc | Cancela un arrastre en curso |
Ejemplos #
Las citas de un DataStore, y lo que el usuario hace con ellas #
El DataStore ids_appts (variable de instancia) tiene las columnas subject, start_date, end_date, location, room, category y customer. Las cuatro primeras desempeñan su rol por su nombre; room lo recibe de 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()
Crear y eliminar #
// 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)
Una columna por sala #
// 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
Tarjetas e información propias #
// 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}"
Rechazar un desplazamiento #
// 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
Cargar solo lo que se ve #
Con años de historial, no hace falta leerlo todo: ue_date_changed da el intervalo en pantalla en cada navegación, y en la primera visualización. Aquí d_appointments recibe dos argumentos datetime, inicio y fin del intervalo.
// 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)
Su menú sobre una cita #
// 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
Buenas prácticas #
- Enmarque una serie de adiciones con
of_set_redraw(/*on*/ false)/of_set_redraw(/*on*/ true): las citas aparecen de una sola vez. - Para datos que viven en una base, prefiera
of_from_datastorea un bucle deof_add_appointment: una sola transferencia, y cada evento le devuelve la fila. - Recargue (
of_from_datastore) después de cualquierInsertRow,DeleteRow,SortoFilterdel DataStore: la clave de una cita es un número de fila. - Escriba las fechas como
"yyyy-mm-dd hh:mm", nunca en el formato regional del equipo: es el único que el calendario lee en todas partes. - En una plantilla, rodee un campo opcional con
{?campo}…{/campo}: una tarjeta sin lugar no muestra un « ; » huérfano. - Con un historial largo, cargue el intervalo visible en
ue_date_changeden lugar de todo el DataStore. - Para una regla de negocio (ninguna cita el fin de semana, ningún solapamiento en una sala),
ib_veto_changesyue_appointment_changingrechazan antes de que la tarjeta se mueva.
Límites de la 4.0 #
Lo que el calendario no hace — conviene saberlo antes de elegirlo:
- Periodicidad: ni series (reglas RRULE), ni excepciones, ni edición « esta repetición / toda la serie ».
ib_recurringsolo pone un signo en la tarjeta: cada repetición es una cita (una fila del DataStore) que su aplicación genera por sí misma. Un motor de periodicidad está previsto para una versión posterior. - Zonas horarias: la hora es local flotante (véase Las fechas); ninguna segunda escala horaria, ninguna conversión.
- Vista cronológica (recursos en filas, tiempo en columnas) y minicalendario de navegación: ausentes; agrupe por recurso (
GROUP_RESOURCE) en las vistas día y semana. - iCalendar: ni importación ni exportación de archivos
.ics. - Impresión: ninguna; el calendario se dibuja solo en pantalla.
- Teclado: se selecciona, se abre, se elimina y se navega con el teclado, pero no se crea ni se mueve una cita sin el ratón.
- Fecha y hora en dos columnas: un inicio escrito en dos columnas del DataStore no se asigna; únalo en una columna
datetimeen la consulta.
Heredado de la base común #
Estos miembros existen en todos los componentes visuales — no son propios de este. Se detallan una sola vez, en los capítulos transversales; esta tabla solo dice dónde leerlos.
| Miembros | Función | Detallado en |
|---|---|---|
of_count · of_keys_at · of_has | Recorrer lo que el componente contiene | 3.2 Los items |
of_reset | Poner el componente a cero | 3.6 Poner un componente a cero: of_reset() |
of_register_shortcut · of_clear_shortcuts | Atajos de teclado del componente | 3.5 Los atajos de teclado |
of_is_created · of_is_ready · of_get_last_error | Si ha nacido, si está listo, qué ha fallado | 3.7 Diagnóstico |
of_save_as_png · of_save_as_jpg | Exportar el render como imagen | 3.8 Exportar la representación como imagen |
of_set_redraw | Agrupar los cambios en un solo repintado | 3.10 Buenas prácticas |
of_preload_icons | Iconos mostrados sin retardo | Visualización instantánea: of_icon |
of_set_translation | Traducir una etiqueta del componente | 5.2 Adaptar una etiqueta: of_set_translation |
of_focus_webview | Dar el foco al componente | 6.4 Teclado y foco |
of_print · of_print_to_pdf | Imprimir, o escribir un PDF | 6.9 Imprimir |
of_set_property · of_get_property · of_component_name | Controlar una propiedad por su nombre | 3.1 El motor de propiedades |
Dos ayudas no se heredan: of_icon y of_escape_markup viven en n_pbt_utils. Declare uno — n_pbt_utils lnv_utils, nada que crear — y llámelas sobre él.