Script: Listeneinstellungen kopieren

Kopiert die Listeneinstellungen von Ordner, LinkContainern und Ressourcenplanungsansichten

Kopiert die Listeneinstellung eines Ordners, LinkContainers oder einer Ressourcenplanungsansicht.

Es erscheint ein Dialog, wo eine der folgenden Aktionen ausgewählt werden kann:

  • Transfer settings from another list: Kopiert die Listeneinstellungen einer anderen Liste in die aktuelle. Das Objekt, von welchem die Listeneinstellungen übertragen werden sollen, kann in einem Vertec Browser ausgewählt werden. 
  • Transfer this list settings: Kopiert die Listeneinstellungen der aktuellen Liste in eine andere. Das Objekt, in welches die Listeneinstellungen übertragen werden sollen, kann in einem Vertec Browser ausgewält werden.
  • Load settings from file: Die Listeneinstellungen werden aus einer vorher gespeicherten JSON Datei vom Filesystem geladen. Es erscheint ein Dateibrowser, wo die Datei ausgewählt werden kann.
  • Save settings to file: Speichert die aktuellen Listeneinstellungen in eine JSON Datei auf dem Filesystem. Es erscheint ein Speicherdialog mit dem voreingestellten Filenamen: YYYYMMDD-Containername-ObjID. Dieser kann bei Bedarf auch überschrieben werden.

ACHTUNG: Es ist wichtig, dass sorgfältig darauf geachtet wird, was übertragen wird. Werden Listeneinstellungen an Orte übertragen, wo sie nicht passen, kann Vertec damit zum Absturz gebracht werden.

Deshalb empfehlen wir Ihnen, das Script nicht zu registrieren, sondern es über den Script Editor zu verwenden.

Sie können Listeneinstellungen, die Sie für alle Listen einer Klasse (z.B. alle Adresslisten) verwenden möchten, auch als Standard hinterlegen. Siehe dazu den Artikel über die Listeneinstellungen - Button Als Standard speichern.

Versionen

Vertec Version Besonderheit Version Script
Ab Vertec 6.8 Verwendet das englische Datenmodell TransferListSettings.py

Ausführen

Ordner und LinkContainer

Das Script muss auf dem Ordner/LinkContainer ausgeführt werden. Wählen Sie diesen an und öffnen Sie dann den Script Editor. Führen Sie das Script darin aus. 

Ressourcenplanungsansichten

Das Kopieren von Listeneinstellungen erfolgt auf der Definition der Ressourcenplanungsansicht. Wählen Sie diese an und öffnen Sie dann den Script Editor. Führen Sie das Script darin aus.

Scripttext

# coding: windows-1252
#
# Name: Transfer list settings
# Classes: Entry
# CondExpression: None
# Selectedobjectsscript: Y
# Condexpression: self->size = 1
# ExtendedRights: N
#
# Description: Copies list settings in Vertec or to / from a file.
#
# 2025-03-06, CBR: Created.
# 2026-08-21, CBR: Updated for concept.
#
# Version = 101


import vtcapp
import traceback
import json
import re


# region constants

LANGUAGES = vtcapp.evalocl("Language.allInstances.languagename->asSet") + ["NV"]
TITLE = vtcapp.translate("Transfer list settings")

MEMBERS_SOURCE = ["tabsPerClass", "controllerClassName"]
MEMBERS_GRIDDEF = ["rowHeight", "ghostrow", "fontColor", "color", "editing", "class"]
MEMBERS_GRIDCOL = ["writeableExpression", "alignment", "orderIdx", "color", "fontColor", "controlName", "rendererName", "totals", "controlDefinition", "expression", "readOnly", "sortOrder", "tabstop", "width", "isFixed", "remarks", "isDynamic", "enableSpellCheck", "spellCheckLanguageExpression", "visibleExpression", "title"]
MEMBERS_ML = ["title"]


# region action functions

def transfer_from_list(target):
    "Copy another lists settings to this list."

    # Select source
    source = select_folder(target, False)
    if not source:
        return

    # Source to dict
    source_settings = to_dict(source)
    if not source_settings:
        return

    # Dict to target
    from_dict(target, source_settings)


def transfer_to_list(source):
    "Copy this lists settings to another list."

    # Select target
    target = select_folder(source, True)
    if not target:
        return

    # Source to dict
    source_settings = to_dict(source)
    if not source_settings:
        return

    # Dict to target
    from_dict(target, source_settings)


def load_from_file(target):
    "Updates the current list settings from a file."

    # Select file
    try:
        filename, file = vtcapp.requestfilefromclient(TITLE, "", "JSON|*.json")
    except RuntimeError:
        return

    # Source to dict
    source_settings = json.loads(file.decode('utf-8'))
    if not source_settings:
        return

    # Dict to target
    from_dict(target, source_settings)


def save_to_file(source):
    "Saves the current list setttings to a file."

    # Source to dict
    settings_dict = to_dict(source)

    # Save file
    filename = settings_dict.get('filename', '')
    file = json.dumps(settings_dict).encode('utf-8')

    vtcapp.sendfile(file, filename, True, False)


# region internal functions

def _save_getattr(vtc_object, member, settings):
    "Savely gets an attribute."

    normalized_member = member.lower()

    if hasattr(vtc_object, normalized_member):

        try:
            if normalized_member in MEMBERS_ML:
                settings[normalized_member] = {}
                for language in LANGUAGES:
                    settings[normalized_member][language] = vtc_object.getmlvalue(normalized_member, language)
            else:
                settings[normalized_member] = getattr(vtc_object, normalized_member)
        except Exception:
            traceback.print_exc()

    return settings


def _save_setattr(vtc_object, member, settings):
    "Savely sets an attribute."

    normalized_member = member.lower()

    if normalized_member not in settings.keys():
        return

    try:
        if normalized_member in MEMBERS_ML:
            for language in LANGUAGES:
                vtc_object.setmlvalue(normalized_member, settings[normalized_member][language], language)
        else:
            setattr(vtc_object, normalized_member, settings[normalized_member])
    except Exception:
        traceback.print_exc()


def _get_filename(source):
    "Returns the filename for the given source."

    date_string = vtcapp.currentdate().strftime('%Y%m%d')
    source_string = source.evalocl("asstring")
    source_reference = source.evalocl("objid")

    filename = "{}_{}_{}.json".format(date_string, source_string, source_reference)

    # Replace invalid characters with underscore and replace consecutive underscores.
    filename = re.sub(r'[\\/:*?"<>|]', '_', filename)
    filename = re.sub(r'_+', '_', filename)

    return filename


def _source_to_dict(source):
    "Translate the source to a settings dict."

    source_settings = {
        'griddefs': [],
        'filename': _get_filename(source),
    }

    for member in MEMBERS_SOURCE:
        source_settings = _save_getattr(source, member, source_settings)

    return source_settings


def _dict_to_target(target, target_setting):
    "Translate the settings dict to the target"

    for member in MEMBERS_SOURCE:
        _save_setattr(target, member, target_setting)


def _griddef_to_dict(griddef):
    "Translate the grid def to a settings dict."

    griddef_settings = {
        'gridcols': []
    }

    for member in MEMBERS_GRIDDEF:
        griddef_settings = _save_getattr(griddef, member, griddef_settings)

    for gridcol in griddef.evalocl("gridcols->orderby(orderidx)"):
        griddef_settings['gridcols'].append(_gridcol_to_dict(gridcol))

    return griddef_settings


def _dict_to_griddef(griddef, griddef_setting):
    "Translate the settings dict to a grid def ."

    for member in MEMBERS_GRIDDEF:
        _save_setattr(griddef, member, griddef_setting)

    for gridcol_setting in griddef_setting.get('gridcols', []):

        gridcol = vtcapp.createobject('GridColDef')
        griddef.gridcols.append(gridcol)
        _dict_to_gridcol(gridcol, gridcol_setting)


def _gridcol_to_dict(gridcol):
    "Translate the grid col def to a dict."

    gridcol_settings = {}

    for member in MEMBERS_GRIDCOL:
        gridcol_settings = _save_getattr(gridcol, member, gridcol_settings)

    return gridcol_settings


def _dict_to_gridcol(gridcol, gridcol_setting):
    "Translate the grid col def to a settings dict."

    for member in MEMBERS_GRIDCOL:
        _save_setattr(gridcol, member, gridcol_setting)


# region helper functions

def to_dict(source):
    "Transfers the list settings to a dict."

    if not source:
        return None

    if source.evalocl("oclIsKindOf(LinkContainer)"):
        source = source.rolle

    # Save global settings
    source_settings = _source_to_dict(source)

    # Save griddefs
    for griddef in source.evalocl("griddefs"):
        source_settings['griddefs'].append(_griddef_to_dict(griddef))

    return source_settings


def from_dict(target, target_setting):
    "Transfers the list settings from a dict."

    if not target:
        return

    if target.evalocl("oclIsKindOf(LinkContainer)"):
        target = target.rolle

    # Restore global settings
    _dict_to_target(target, target_setting)

    # Remove old grids
    for griddef in list(target.evalocl("griddefs")):
        target.griddefs.remove(griddef)

    # Create new griddefs
    for griddef_setting in target_setting.get('griddefs', []):

        griddef = vtcapp.createobject("GridDef")
        target.griddefs.append(griddef)
        _dict_to_griddef(griddef, griddef_setting)


def select_folder(base, base_is_source=True):
    "Lets the user select a destination or target."

    title = "{} {}: '{}'".format(TITLE, vtcapp.translate("from" if base_is_source else "to"), base)
    return vtcapp.selectobjectintree(title, [], "", "AbstractFolder, LinkContainer, ViewType")


def select_action():
    "Lets the user select which action should be performed."
    dlgDefinition="""
    <Dialog Title="Transfer list settings" Width="500">
        <Group Label="Select action" ShowLabel="True">
            <ListBox Name="AuswahlBox" Lines="4"/>
        </Group>
        <Dialog.Buttons>
            <Button Text="OK" IsAccept="True" Command="{Binding OkCommand}" />
            <Button Text="Cancel" IsCancel="True" Command="{Binding CancelCommand}" />
        </Dialog.Buttons>
    </Dialog>
    """
    initValues = {}
    action = None
    initValues["AuswahlBox.Items"] = (vtcapp.translate("Transfer settings from another list"), vtcapp.translate("Transfer this list settings"), vtcapp.translate("Load settings from file"), vtcapp.translate("Save settings to file"))
    ok, values = vtcapp.showcustomdialog(dlgDefinition, initValues)
    if ok:
        actions = {0: 'transfer_from_list', 1:'transfer_to_list', 2: 'load_from_file', 3: 'save_to_file'}
        action = actions.get(values["AuswahlBox"])

    return action

# region main function

# We cannot use normal main entry, because we need locals()
source = argobject  # type: ignore # noqa

# Check conditions
if not source.eval("oclisKindOf(AbstractFolder) or oclisKindOf(LinkContainer) or oclisKindOf(ViewType)"):
    raise Exception(vtcapp.translate("This script only works for Folders, Link Containers and Ressource Planning views."))

# Select action
action = select_action()
if action:

    # Execute action
    try:
        locals()[action](source)

    # Catch error. Display short message and print long message.
    except Exception as e:
        traceback.print_exc()
        message = "{}\n\n{}\n\n({})".format(vtcapp.translate("An error occurred."),
                                            e,
                                            vtcapp.translate("See Python console for more information"))
        vtcapp.msgbox(message)

Netherlands

United Kingdom