Our pure JavaScript Scheduler component


Post by jqueija »

Hi, I'd like to get some assistance if possible due to some issues I need to solve.

1 - I am successfully able to export my scheduler to excel, but after it happens, I get an error when opening the Excel file. Excel then offers to repair the file which successfully does and I can enter the file. Is there anything wrong on my code that may be causing this error in excel?

2 - I need to filter all rows that won't have a specific value in them. How can I do that?. At the moment I've been able to successfully alter some values per each row/column (i. e. I am converting statusId to its correct assigned label name) but don't know how to avoid an entire row to be exported when a specific cell does not have a value for that row.

3 - I'm trying to use the "width" prop but it doesn't seem to alter/work the column width at all.

I'm pasting my component and also captures of the error I get from Excel as well as the log file.

Thanks and I look forward to hearing from you,

import React, { useCallback, useRef, useEffect, useState, lazy } from 'react';
import { useDispatch } from 'react-redux'
import zipcelx from 'zipcelx';
import Moment from 'moment'
import { extendMoment } from 'moment-range'
import { BryntumScheduler } from '@bryntum/schedulerpro-react'
import { Menu, ColumnStore, WidgetColumn } from '@bryntum/schedulerpro/schedulerpro.umd'
import '../../styles/styles.scss'

import {
    getResourcesSchedulerSearch,
    setEmptyGetResourcesSchedulerSearch,
    setFormFilters
} from '../../redux/actions'

import {
    errorAlert,
    getMessageTranslation,
    convertToSelectableValuesTranslated,
    getTranslation,
    decimalDaysToDateValues
} from '../../utils'

import {
    buildFiltersResourcesSchedulerSearchBusiness,
    initModelResourcesSchedulerSearchBusiness,
    getViewPresetsTaskSchedulerBusiness,
    getViewStartDateTaskSchedulerBusiness,
    getViewEndDateTaskSchedulerBusiness,
    getTimeSpanFromViewPresetTaskSchedulerBusiness,
    getLocaleTaskSchedulerBusiness,
    mapToSchedulerResourcesTasks,
    personalTasksRemovalTool,
    getScheduleTaskDurationBusiness
} from '../../business'

class ExtendedWidgetColumn extends WidgetColumn {
    static get type() {
        return 'extendedwidget'
    }
    onBeforeWidgetSetValue(widget, renderData) {
        if (widget.type === 'button') {
            widget.hidden = renderData.record.get('resourceTypeCode') !== 'Resources Groups'
        }
    }
}
ColumnStore.registerColumnType(ExtendedWidgetColumn);

const TaskSchedulerSearchResourcesPopup = lazy(() => import('../TaskSchedulerSearchResourcesPopup'))
const TaskSchedulerSearchProjectIdPopup = lazy(() => import('../TaskSchedulerSearchProjectIdPopup'))

const Popup = lazy(() => import('../../components/Popup'))

const SchedulerPro = ({
    user,
    fieldsPage,
    translation,
    language,
    scenario,
    localization,
    userConfiguration,
    companies,
    clientsClassesScenaries,
    onTranslation,
    messages,
    usersCostCenters,
    schedulerResourcesResults,
    schedulerResources,
    schedulersStatus,
    setSelectedResources,
    schedulerSearchResults,
    bookingTasksSearchResults,
    handleTaskEditionClick,
    handleBookingEditionClick,
    refreshSelectedResources,
    setRefreshSelectedResources,
    personalTasksSearchResults,
    personalTasksFromScheduler,
    setPersonalTasksFromScheduler,
    setOriginalSelectedResource
}) => {
    const scheduler = useRef()
    const dispatch = useDispatch()
    const [openResourcesSchedulerSearchPopup, setOpenResourcesSchedulerSearchPopup] = useState(false)
    const [openResourcesProjectIdSearchPopup, setOpenResourcesProjectIdSearchPopup] = useState(false)
    const [cecos, setCecos] = useState([])
    const [projectId, setProjectId] = useState(null)
    const [searchModel, setSearchModel] = useState(initModelResourcesSchedulerSearchBusiness())
    const presets = getViewPresetsTaskSchedulerBusiness()
    const moment = extendMoment(Moment)
    const commonEvents = schedulerSearchResults.map(data => mapToSchedulerResourcesTasks(data))
    const personalEvents = personalTasksSearchResults.map(pt => mapToSchedulerResourcesTasks(pt, schedulerSearchResults))
    const bookingEvents = bookingTasksSearchResults.map(data => mapToSchedulerResourcesTasks(data))
    const events = [...commonEvents, ...personalEvents, ...bookingEvents]

useEffect(() => {
    if (events.length > 0) {
        if (projectId !== null) {
            scheduler.current.instance.events = scheduler.current.instance.events.filter(se => se.data.projectId === parseInt(projectId))
        }
    }
}, [events])

useEffect(() => {
    initializeSelectors()
    handleSearch({ ...searchModel, scenaryId: scenario.id, userId: user.id })
}, [])

const initializeSelectors = useCallback(() => {
    dispatch(setEmptyGetResourcesSchedulerSearch())
}, [fieldsPage])

useEffect(() => {
    if (language.isoCode === 'es-ES' && !scheduler.current.instance.localeManager.locales["es-ES"]) {
        scheduler.current.instance.localeManager.registerLocale('es-ES', {
            desc: 'Spanish',
            locale: {
                ...translation('bryntum_scheduler_locale_config'),
                ...getLocaleTaskSchedulerBusiness(language, fieldsPage, scenario)
            }
        });
    }
    if (language.isoCode === 'en-GB' && !scheduler.current.instance.localeManager.locales["en-GB"]) {
        scheduler.current.instance.localeManager.registerLocale('en-GB', {
            desc: 'English',
            locale: {
                ...translation('bryntum_scheduler_locale_config'),
                ...getLocaleTaskSchedulerBusiness(language, fieldsPage, scenario)
            }
        });
    }
    scheduler.current.instance.localeManager.applyLocale(language.isoCode);
}, [language])

useEffect(() => {
    if (refreshSelectedResources) {
        setRefreshSelectedResources(false)
        scheduler.current.instance.deselectAll()
    }
}, [refreshSelectedResources])

useEffect(() => {
    if (personalTasksFromScheduler.length === 0) {
        const newPersonalTasks = scheduler.current.instance.events.filter(se => se.data.type !== null)
        setPersonalTasksFromScheduler(newPersonalTasks)
    }
}, [personalTasksFromScheduler, (scheduler.current !== undefined && scheduler.current.instance.events.length > 0)])

const handleSearch = (filters) => {
    setSearchModel(filters)
    dispatch(setEmptyGetResourcesSchedulerSearch())
    const businessResult = buildFiltersResourcesSchedulerSearchBusiness(filters)
    if (!businessResult.hasErrors) {
        dispatch(setFormFilters(businessResult.content))
        dispatch(getResourcesSchedulerSearch(businessResult.content))
    } else {
        errorAlert(getMessageTranslation(language.id, messages, 'code', businessResult.resultOperations[0].message))
    }
}

const handleOnPopupSearch = (qualificationName, costCenterIds) => {
    setOpenResourcesSchedulerSearchPopup(false)
    handleSearch({ ...searchModel, qualificationName: qualificationName, costCenterIds: costCenterIds })
}

const handleOnPopupSearchByProjectId = (projectId) => {
    setOpenResourcesProjectIdSearchPopup(false)
    setProjectId(projectId)
    scheduler.current.instance.events = scheduler.current.instance.events.filter(se => se.data.projectId === parseInt(projectId))
}

const handleClearProjectId = () => {
    setProjectId(null)
    scheduler.current.instance.events = events
}

const handleOnOpenResourcesSchedulerSearchPopup = () => {
    setOpenResourcesSchedulerSearchPopup(true)
}

const handleOnOpenProjectIdSchedulerSearchPopup = () => {
    setOpenResourcesProjectIdSearchPopup(true)
}
const handleClearClick = () => {
    setCecos([])
    setSelectedResources([])
    handleSearch({ ...initModelResourcesSchedulerSearchBusiness(), scenaryId: scenario.id, userId: user.id })
}

const selectionChangeHandler = ({ selection }) => {
    if (selection[0] !== undefined && selection[0].data) {
        setSelectedResources(selection.map(s => s.data))
        setOriginalSelectedResource(selection.map(s => s.data))
    } else if (selection[0] === undefined) {
        setSelectedResources([])
        setOriginalSelectedResource([])
    } else {
        return
    }
}

const getSchedulerStatusValue = (data) => {
    return !!data?.eventRecord?.statusId && schedulersStatus?.length > 0
        ? convertToSelectableValuesTranslated(schedulersStatus, language.id).filter(schedulerStatus => schedulerStatus.value === data.eventRecord.statusId)[0]?.label
        : ''
}

const handlePresetView = (e, base) => {
    const schedulerInst = scheduler.current.instance
    const timeSpanBusinessResult = getTimeSpanFromViewPresetTaskSchedulerBusiness(schedulerInst.startDate, base)
    schedulerInst.viewPreset = presets.find(p => p.base === timeSpanBusinessResult.viewPresetName)
    schedulerInst.setTimeSpan(timeSpanBusinessResult.startDate, timeSpanBusinessResult.endDate)
}

const handleShiftPrevious = () => {
    scheduler.current.instance.shiftPrevious()
}

const handleShiftNext = () => {
    scheduler.current.instance.shiftNext()
}

const handleExcelExporter = () => {
    scheduler.current.instance.features.excelExporter.export({
        filename: 'Mi Exports de Excel',
        exporterConfig: {
            columns: [
                { text: `${onTranslation(language.id, fieldsPage, "scheduler_taskscheduler_eventTooltip_name", scenario.id)}`, field: 'name' },
                { text: `${onTranslation(language.id, fieldsPage, "scheduler_taskscheduler_eventTooltip_resourceType", scenario.id)}`, field: 'resourceType' },
            ],
            eventColumns: [
                {
                    text: `${onTranslation(language.id, fieldsPage, "scheduler_taskscheduler_eventTooltip_projectId", scenario.id)}`,
                    field: 'projectId',
                    width: 400
                },
                { text: `${onTranslation(language.id, fieldsPage, "scheduler_taskscheduler_eventTooltip_taskId", scenario.id)}`, field: 'name', width: 400 },
                {
                    text: `${onTranslation(language.id, fieldsPage, "scheduler_taskscheduler_eventTooltip_status", scenario.id)}`,
                    field: 'statusId',
                    width: 400,
                    renderer: ({ value }) => {
                        const convertedValue = convertToSelectableValuesTranslated(schedulersStatus, language.id).filter(schedulerStatus => schedulerStatus.value === value)[0]?.label
                        return convertedValue
                    }
                },
                { text: `${onTranslation(language.id, fieldsPage, "scheduler_taskscheduler_eventTooltip_date", scenario.id)}`, field: 'startDate', width: 800 },
                {
                    text: /*`${onTranslation(language.id, fieldsPage, "scheduler_taskscheduler_eventTooltip_status", scenario.id)}`*/ 'Duración',
                    field: 'duration',
                    width: 800,
                    renderer: ({ value }) => {
                        return decimalDaysToDateValues(value)
                    }
                },
                { text: `${onTranslation(language.id, fieldsPage, "scheduler_taskscheduler_eventTooltip_createdBy", scenario.id)}`, field: 'createdUser', width: 800 },
                {
                    text: `${onTranslation(language.id, fieldsPage, "scheduler_taskscheduler_eventTooltip_on", scenario.id)}`,
                    field: 'createdDate',
                    width: 800,
                    renderer: ({ value }) => {
                        const convertedValue = moment(value).format('DD/MM/YYYY HH:mm')
                        return convertedValue
                    }
                }
            ]
        }
    })
}

const schedulerConfig = !!schedulerResources && !!events && {
    enableRecurringEvents: true,
    eventStyle: 'colored',
    eventColor: null,
    resources: schedulerResourcesResults.map(sr => (sr)),
    events: events,
    features: {
        eventResize: false,
        stripe: false,
        eventDrag: false,
        eventDragCreate: false,
        eventMenu: false,
        cellMenu: false,
        eventEdit: false,
        scheduleMenu: false,
        timeRanges: {
            enableResizing: false,
            showCurrentTimeLine: true,
            showHeaderElements: true,
            tooltipTemplate: ({ timeRange }) => timeRange.name
        },
        eventTooltip: {
            template: (data) =>
                (data.eventRecord.data.type !== 'personal')
                    ?
                    `
                    <div class="b-sch-event-tooltip b-sch-event-tooltip--no-margin">
                        <div class="tooltip-content tooltip-content--centered">
                            ${!!data?.eventRecord?.projectId ? `${onTranslation(language.id, fieldsPage, "scheduler_taskscheduler_eventTooltip_projectId", scenario.id)}: ${data.eventRecord.projectId}<br/>` : ''}
                            ${!!data?.eventRecord?.name ? `${onTranslation(language.id, fieldsPage, "scheduler_taskscheduler_eventTooltip_taskId", scenario.id)}: ${data.eventRecord.name}<br/>` : ''}
                            ${onTranslation(language.id, fieldsPage, "scheduler_taskscheduler_eventTooltip_resourceType", scenario.id)}: ${!!data?.eventRecord?.resource?.resourceType ? data.eventRecord.resource.resourceType : ''} <br/>
                            ${!!getSchedulerStatusValue(data) ? `${onTranslation(language.id, fieldsPage, "scheduler_taskscheduler_eventTooltip_status", scenario.id)}: ${getSchedulerStatusValue(data)}<br/>` : ''}
                            <div>    
                                <div class="flex flex--row flex--space-between">
                                    ${onTranslation(language.id, fieldsPage, "scheduler_taskscheduler_eventTooltip_date", scenario.id)}: ${moment(data.startDate).format('DD/MM/YYYY')}
                                    <div class="b-sch-clockwrap b-sch-clock-hour clock--centered">
                                        <div class="b-sch-clock">
                                            <div class="b-sch-hour-indicator">${moment(data.startDate).format('MMM')}</div>
                                            <div class="b-sch-minute-indicator">${moment(data.startDate).format('D')}</div>
                                            <div class="b-sch-clock-dot"></div>
                                        </div>
                                        <span class="b-sch-clock-text"> ${!!getScheduleTaskDurationBusiness(data.endDate, data.startDate) ? `: ${getScheduleTaskDurationBusiness(data.endDate, data.startDate)}` : ''}</span>
                                    </div>
                                </div>
                            </div>
                        </div>
                        <div class="divider"></div>
                        <div class="tooltip-content">
                            ${onTranslation(language.id, fieldsPage, "scheduler_taskscheduler_eventTooltip_createdBy", scenario.id)}: ${!!data?.eventRecord?.createdUser ? data.eventRecord.createdUser : ''} ${onTranslation(language.id, fieldsPage, "scheduler_taskscheduler_eventTooltip_on", scenario.id)} ${moment(data.eventRecord.createdDate).format('DD/MM/YYYY HH:mm')}<br/>
                        </div>
                    </div>
                    `
                    :
                    null
        },
        timeAxisHeaderMenu: {
            items: {
                zoomLevel: false,
                currentTimeLine: false
            }
        },
        excelExporter: {
            zipcelx,
            group: 'role',
            dateFormat: 'DD/MM/YYYY HH:mm'
        }
    },
    columns: [
        {
            type: 'resourceInfo',
            text: 'L{resourceList_filter_orderBy_name}',
            width: '11.5rem',
            editor: false,
            showEventCount: false,
            renderer: ({ record }) => {
                let startDate = (!!record.eventStore.lastDateRange?.startDate && record.eventStore.lastDateRange?.startDate !== undefined) && new Date(record.eventStore.lastDateRange?.startDate)
                let endDate = (!!record.eventStore.lastDateRange?.endDate && record.eventStore.lastDateRange?.endDate !== undefined) && new Date(record.eventStore.lastDateRange?.endDate)
                let range = ((!!startDate && startDate !== undefined) && (!!endDate && endDate !== undefined)) && moment.range(startDate, endDate)
                const taskCounter = personalTasksRemovalTool(record, range)
                return {
                    class: 'b-resource-info',
                    children: [
                        {
                            tag: 'div',
                            class: 'b-resource-avatar b-resource-initials',
                            html: record.initials
                        },
                        {
                            tag: 'dl',
                            html: `<dl>
                            <dt>${record.name}</dt>
                            <dd>${taskCounter}${getTranslation(language.id, fieldsPage, "taskscheduler_taskEventName", scenario.id)}${(taskCounter !== 1 ? 's' : '')}</dd>
                            </dl>`
                        },
                    ]
                };
            }
        },
        {
            text: 'L{resourceList_filter_orderBy_resourceType}',
            field: 'resourceType',
            width: '7.5rem',
            editor: false,
            filterable: {
                filterField: {
                    placeholder: 'L{Column.resourceList_filter_tooltip_resourceType}',
                }
            }
        },
        {
            width: '1rem',
            type: 'extendedwidget',
            widgets:
                [{
                    cls: 'b-transparent',
                    type: 'button',
                    tooltip: 'L{Widgets.resourceList_resource_btn_members}',
                    icon: 'b-fa b-fa-fw b-fa-ellipsis-v',
                    onAction: ({ source: btn }) => {
                        const menu = btn.menu || (btn.menu = new Menu({
                            cls: 'b-transparent',
                            forElement: btn.element,
                            items: [
                                {
                                    cls: 'b-transparent',
                                    text: onTranslation(language.id, fieldsPage, "resourceList_resource_btn_members", scenario.id),
                                    onItem({ item }) {
                                        console.log('showing team members', item);
                                    }
                                }
                            ],
                            focusOnHover: false,
                        }));
                        menu.show();
                    }
                }]
        },
    ],
    barMargin: 5,
    rowHeight: 40,
    createEventOnDblClick: false,
    enableDeleteKey: false,
    filterBarFeature: true,
    startDate: getViewStartDateTaskSchedulerBusiness(),
    endDate: getViewEndDateTaskSchedulerBusiness(),
    autoAdjustTimeAxis: true,
    presets: presets,
    viewPreset: presets[0],
    useInitialAnimation: 'slide-from-left',
    tbar: [
        {
            type: 'buttongroup',
            cls: 'tbar-left',
            width: '22rem',
            items: [
                {
                    type: 'button',
                    tooltip: onTranslation(language.id, fieldsPage, "resourceList_filter_tooltip_popup", scenario.id),
                    cls: 'b-transparent',
                    icon: 'b-fa-search',
                    onClick: () => handleOnOpenResourcesSchedulerSearchPopup()
                },
                {
                    type: 'button',
                    tooltip: onTranslation(language.id, fieldsPage, "resourceList_filter_tooltip_deleteFilters", scenario.id),
                    cls: 'b-transparent',
                    icon: 'b-fa-trash',
                    onClick: () => handleClearClick()
                }
            ]
        },
        {
            type: 'buttongroup',
            cls: 'tbar-left',
            style: 'flex-grow: 1',
            items: [
                {
                    type: 'button',
                    tooltip: onTranslation(language.id, fieldsPage, "resourceList_filter_tooltip_popup", scenario.id),
                    cls: 'b-transparent',
                    icon: 'b-fa-filter',
                    onClick: () => handleOnOpenProjectIdSchedulerSearchPopup()
                },
                {
                    type: 'button',
                    tooltip: onTranslation(language.id, fieldsPage, "resourceList_filter_tooltip_popup", scenario.id),
                    cls: 'b-transparent',
                    icon: 'b-fa-file-export', // icono del excel para exportación
                    onClick: () => handleExcelExporter()//handleOnOpenProjectIdSchedulerSearchPopup()
                },
            ]
        },
        {
            type: 'buttongroup',
            cls: 'tbar-right',
            items: [
                {
                    type: 'button',
                    ref: 'todayButton',
                    text: 'L{Header.today}',
                    cls: 'b-transparent',
                    onAction: (e, base = 'today') => handlePresetView(e, base)
                },
                {
                    type: 'button',
                    ref: 'hoursButton',
                    text: 'L{Header.day}',
                    cls: 'b-transparent',
                    onAction: (e, base = 'hourAndDay') => handlePresetView(e, base)
                },
                {
                    type: 'button',
                    ref: 'daysButton',
                    text: 'L{Header.week}',
                    cls: 'b-transparent',
                    onAction: (e, base = 'weekAndDay') => handlePresetView(e, base)
                },
                {
                    type: 'button',
                    ref: 'monthsButton',
                    text: 'L{Header.month}',
                    cls: 'b-transparent',
                    onAction: (e, base = 'weekAndMonth') => handlePresetView(e, base)
                },
                {
                    type: 'button',
                    icon: 'b-fa-angle-left',
                    tooltip: 'L{Header.previousDate}',
                    cls: 'b-transparent',
                    onAction: () => handleShiftPrevious()
                },
                {
                    type: 'button',
                    icon: 'b-fa-angle-right',
                    tooltip: 'L{Header.nextDate}',
                    cls: 'b-transparent',
                    onAction: () => handleShiftNext()
                }
            ]
        }
    ],
    listeners: {
        eventDblClick({ eventRecord }) {
            if (!eventRecord.type || eventRecord.type !== 'personal') {
                eventRecord?.type === 'booking' ? handleBookingEditionClick(eventRecord.name) : handleTaskEditionClick(eventRecord.name)
            } else {
                return false
            }
        }
    },
    eventBodyTemplate: data =>
        (data.eventType !== 'personal')
            ?
            `
            <div class="b-sch-event-header">${data.headerText}</div>
            <div class="b-sch-event-footer">${data.footerText}</div>
            `
            :
            ''
    ,
    eventRenderer({ eventRecord, resourceRecord, renderData }) {
        if (eventRecord.cls.value === '' || eventRecord.cls.value === null) {
            renderData.eventStyle = 'colored'
            if (eventRecord.color !== null) {
                renderData.eventColor = eventRecord.color
            }
        } else {
            renderData.eventStyle = null
            renderData.eventColor = null
        }
        return {
            headerText: moment(eventRecord.startDate).format(this.localeManager.locale.PresetManager[this.viewPreset.base].displayDateFormat),
            footerText: eventRecord.name || '',
            eventType: !!eventRecord.type ? eventRecord.type : ''
        }
    }
};

return (
    <>
        <BryntumScheduler
            ref={scheduler} {...schedulerConfig}
            style={{ headerHeight: '1rem' }}
            onSelectionChange={selectionChangeHandler}
        ></BryntumScheduler>
        <Popup
            openPopup={openResourcesSchedulerSearchPopup}
            setOpenPopup={setOpenResourcesSchedulerSearchPopup}
            title={onTranslation(language.id, fieldsPage, 'popup_resourceSearch_title', scenario.id)}
            maxWidth={"sm"}
        >
            <TaskSchedulerSearchResourcesPopup
                fieldsPage={fieldsPage}
                translation={translation}
                language={language}
                scenario={scenario}
                localization={localization}
                userConfiguration={userConfiguration}
                companies={companies}
                clientsClassesScenaries={clientsClassesScenaries}
                onTranslation={onTranslation}
                messages={messages}
                usersCostCenters={usersCostCenters}
                handleOnPopupSearch={handleOnPopupSearch}
                searchModel={searchModel}
                cecos={cecos}
                setCecos={setCecos}
            />
        </Popup>
        <Popup
            openPopup={openResourcesProjectIdSearchPopup}
            setOpenPopup={setOpenResourcesProjectIdSearchPopup}
            title={onTranslation(language.id, fieldsPage, 'popup_resourceSearch_title', scenario.id)}
            maxWidth={"sm"}
        >
            <TaskSchedulerSearchProjectIdPopup
                fieldsPage={fieldsPage}
                translation={translation}
                language={language}
                scenario={scenario}
                onTranslation={onTranslation}
                handleOnPopupSearch={handleOnPopupSearchByProjectId}
                searchModel={searchModel}
                projectId={projectId}
                handleClearProjectId={handleClearProjectId}
                setOpenResourcesProjectIdSearchPopup={setOpenResourcesProjectIdSearchPopup}
            />
        </Popup>
    </>
)
}

export default React.memo(SchedulerPro)
Attachments
Capture00.PNG
Capture00.PNG (42.7 KiB) Viewed 652 times
Capture01.PNG
Capture01.PNG (136.24 KiB) Viewed 652 times
Capture02.PNG
Capture02.PNG (24.93 KiB) Viewed 652 times

Post by Animal »

My Spanish is a bit rusty! 😉

Can you provide a translation of the messages.

Also, a diff of the "repaired" XML with our generated XML would be useful so that we know what Excel thinks is better.


Post by jqueija »

Hi Animal, thanks for your reply,

The message for "Capture00.PNG" say this:
"We have encountered a problem with "Excel without fix.xlsx" content. Do you want us to try to retrieve as much content as possible? If you trust the origin of this book, click Yes."

The message for "Capture01.PNG" say this:
"Excel pudo abrir el archivo reparando o quitando el contenido que no se podía leer.
Registros reparados! Información de celda de /xl/worksheets/sheet1.xml parte"

The message in "Capture02.PNG" says this:
"<? xml version = "1.0" encoding = "UTF-8" standalone = "yes"?>
<recoveryLog xmlns = "https://schemas.openxmlformats.org/spreadsheetml/2006/main">
<logFileName> error079200_01.xml </logFileName>
<summary> Errors have been detected in the file "C: \ Users \ flacabaratz \ Downloads \ Excel without fix .xlsx" </summary>
<repairedRecords> <repairedRecord> Repaired records: Cell information from /xl/worksheets/sheet1.xml part </repairedRecord>
</repairedRecords>
</recoveryLog>"

I'm attaching a copy of the fixed file and if you have an email where I can send the corrupt one because as you will see on the attachments, there seems to be a problem when I try to upload it, I get a 503 Error from your server.

Thanks once again and I look forward to hearing from you,

P.S I managed to upload the file to WeTransfer, here's the link so you can download it. Otherwise please provide me with an email I can use to send it.
Link to the file: https://we.tl/t-UIxRAJc95U

Attachments
Capture03.PNG
Capture03.PNG (98.78 KiB) Viewed 620 times
Excel with fix.xlsx
(12.3 KiB) Downloaded 47 times

Post by arcady »

How can we reproduce the exporting issue? Can we have a test case that we could run?
Or can we reproduce this on some of our demos using certain steps?


Post by jqueija »

Hi Arcady, I think I've provided you with the whole piece of code I am using plus errors, plus corrupted excel file as requested by a member of your team. I can not provide you with anymore due to our company's privacy policies.

The only thing I can add is that whenever I comment my eventColumns array of objects inside my handleExcelExporter function, the error dissapears (but this just exports all the basic columns and none of what I really need to see) so I figure it must be something in there that is not acting properly. It is really difficult to get inside Bryntum SchedulerPro's code and I frankly don't know where else to look at. I've checked your examples online, I've downloaded the pdf exporter example for React to see if I can figure something out in beetween both examples, but I can't get rid of the error whatsoever.

Besides that I can tell you that we are working with React 17.0.2, we are using bryntum/schedulerpro 4.3.2 and bryntum/schedulerpro-react 4.3.2 and our Excel is MS Excel version 2110 from MS Office Professional Plus 2019.

Other than that, I would really appreciate if you could help me to figure this out or provide me with a workaround, otherwise we won't be able to use the excelExporter feature in our schedulerPro.


Post by jqueija »

Hello? anyone please can I get some help with this? It would be much appreciated.

Thanks


Post by mats »

I suspect this is caused by String / Number type mismatch. What if you remove

{
                    text: `${onTranslation(language.id, fieldsPage, "scheduler_taskscheduler_eventTooltip_projectId", scenario.id)}`,
                    field: 'projectId',
                    width: 400
                },

from your export config, does that remove the warning?


Post by jqueija »

Hi Mats, thanks for your response and sorry that it took me some time to respond (I took some holidays and came back today).

I confirm you that if I take out this piece of code you have suggested, the error continues to show up. One weird thing I found while doing several tests was that if I open the file through Microsoft Teams the error does not show. This is really awkward due to MS Teams and MS Excel are from the same company but it seems that something in teams makes this export work whilst it does not when opening straight from a double click of from MS Excel.

I look forward to hearing from you.


Post by mats »

We will need a runnable test case in order to debug what is going here.


Post Reply