Profitbase InVision 2022.3 released!

2022.3 brings many new features and enhancements to our low-code platform. A major addition is the ability to define extensions for Packages. This enables Profitbase and partners to develop and distribute add-ons to products. You can also upgrade Packages in multiple Solutions in one go, making it much quicker to upgrade customers to new version of Planner, Risk and Consolidation.

New Features & fixes

Access Control

The new SYS_ObjectPermissions database view enables Solution Developers to write a SQL query to check if a user has access to a Workbook or Workbook Page. Note that the UserUID is the id of the user identity in the InVision access control system, usually a GUID. It is NOT the user name, for example

SELECT HasAccess FROM SYS_ObjectPermissions WHERE UserUID = 'user object id' AND ObjectID = 'workbook or workbook page id'

New Access Control APIs in macros
You can now check if a user has access to Workbooks or Workbook Pages using C# macros. The main difference between using the SYS_ObjectPermissions and the macro APIs is that you can use the Workbook and Page names instead of the ids when querying for user access.

public async Task<string> GetQuery()
    var userHasAccess = await this.AccessControlService.HasWorkbookAccess(this.Context.GetUserUniqueId(), "Name of Workbook");
    // your code

Read more here.


Isolation of PowerShell execution context
This fixes the assembly loading conflict between PowerShell modules using the same .NET assemblies or NuGet packages as the InVision platform.

You no longer need to pass in pbRunContext to PowerShell APIs
You no longer need to pass in pbRunContext to Profitbase PowerShell APIs. The current APIs accepting pbRunContext will still work, but they will be removed in a future version. You should make it a priority switching to using the new APIs.

$bytes = [Profitbase.IO.FileStorage]::ReadAllBytes($PbRunContext, $storageName, $fileName)


$bytes = [Profitbase.IO.FileStorage]::ReadAllBytes($storageName, $fileName)

File Storage API
We have added PowerShell APIs for File Storage. The API enables you to get file information, read and delete files from File Storages using PowerShell.

# Get information about file(s) in the File Storage
$query = "DepartmentID = \"${departmentId}\" && Category = \"${catId}\""
$fileInfos = [Profitbase.IO.FileStorage]::GetFileInfos($storageName, $query)

foreach($fileInfo in $fileInfos)
       # Read a file
       $bytes = [Profitbase.IO.FileStorage]::ReadAllBytes($storageName, $fileInfo.FileName)    
       Write-Output $fileInfo.FileName
       Write-Output $fileInfo.ContextJson
       Write-Output $fileInfo.MimeType
       Write-Output $fileInfo.FileReferenceId

# Delete a file
[Profitbase.IO.FileStorage]::DeleteFile($storageName, $fileName)


Package Manager displays if a Package has dependencies with available upgrades
You can now easily spot if one of the installed Packages has dependencies with available upgrades. This usually happens when a dependency has a patch release.

Package Extensions
We have added support for Package Extensions. This means that developers can create Packages which has the role of extending Products or Libraries. Installing an Extension requires that its dependencies are pre-installed before the extension itself can be installed. If an Extension extends more than one Product Package, at least one of the Product Packages must be pre-installed.

Better overview of dependencies and extensions
This is primarily a developer feature. We now provide a more detailed overview of dependencies and extensions in the Package Upgrade interface. This feature lists the dependency and extension hierarchy of a Package so you can detect possible version conflicts between packages.

Upgrade Packages in multiple Solutions
When upgrading a Package, you can now apply the upgrade to multiple Solutions at the same time. Earlier, upgrades would only be applied to Packages in Work Process Blueprint Solutions. You can now apply upgrades to Versioned Solutions that are in the Deployed or Open state.

Package documentation
We have added support for providing links to Package documentation and upgrade notes. Users can view the docs from the Package installation or upgrade screens.

File Storage

New events
The Upload Completed event is raised when a file has been uploaded. This enables processing a file immediately after it has been uploaded

The File Deleted event is raised when a file has been deleted by the user. It is NOT raised if a file is deleted by the backend, for example using PowerShell.

Bug fix
Fixed bug where file dialog appears behind the dialog window

Spreadsheets (Worksheets + Tables)

Conditions for Context Menu Options
You can now specify conditions for whether a context menu option should be available to the user or not. This enables context menus to be rendered dynamically based on information from the clicked row(s) and the state of the Workbook.

Use JavaScript to define conditions to whether a context menu option should be available or not

Read more about conditions for standard context menu options here
Read more about conditions for custom context menu actions

Support for custom Excel export
We have added a feature to Worksheets, Tables and Table Views that lets Solution Developers override how the Excel export is generated. This enables Solution Developers to fully customize the styling of Excel exports.

Table View

You can now turn off the selection column
This is useful if you want to save space, and only have single select enabled.

Dropdown menus auto sizes to content width
This prevents horizontal scrolling in the dropdown menus of filters.

Bug fixes

  • Fixed issue regarding null values in selector filters. This fixed a crash if your data source contained NULL in one of the columns having dropdown filter.
  • Fixed issue with sorting of date columns. Dates were not sorted correctly.
  • Fixed issue with sorting of text columns where text was sorted using alphanumerical comparison instead of string comparison
  • Fixed issues with missing Norwegian translations
  • Fixed issue where scrolled text content was displayed underneath pinned left or right columns
  • Fixed issue where client side filters did not properly reset after a data reload
  • Fixed issue where the row popdown menu was misplaced
  • Changed checkbox filters to support tri-state (true, false and null) for boolean fields

Data Flow

API for programmatically modifying arguments to global parameters
We have added an API which lets Solution Developers programmatically modify Global Parameters and arguments during execution of a Data Flow. This makes it a lot easier to create nested Data Flows (Data Flows which executes other Data Flows) and provide arguments that are automatically available to any descendant Data Flow without having to explicitly pass the arguments down through the chain.
Read more here.


ItemsSourceFilter API
The Listbox, Dropdown and SplitButton controls now supports using a custom filter to select a subset of items from the ItemsSource. This is useful if you want to use the same data source for two or more list controls, but don’t want to display the same items.

      <Model Name="Customer" Source="@Object[Customers].DbObjectName" Fields="ID,Name" />
    	<List Name="Customers" Source="@Object[Customers].DbObjectName" Fields="ID,Name"/>    	
  	<Function Name="MyFilter" Parameters="items, controlName">
  		return items.filter(item => item.ID !== "Customer1");
  <UI Grid="ui-root">
    <Listbox Name="MyListbox" Row="1" 
        ItemsSourceFilter="MyFilter($Data, $Ctrl.Id)"
    	SelectedValue="{Binding Path:Customer.ID}" />

Data Binding API
Solution Developers can use the new Data Binding API to retrieve all data bindings associated with a data source and force the binding targets (UI elements) to re-render. A typical use case for this feature is when multiple list or selection controls (for example dropdowns) are data bound to the same data source, and you are using the new ItemsSourceFilter feature to ensure that the same items are not available as selectable options in any two list controls.
Read more here.


  • Listbox now supports SelectedItemCssClass, which enables Solution Developers to specify a custom css class to apply to the selected item in the listbox.
  • If SelectedValue is data bound, the corresponding listbox item will be highlighted. The default style of the selected item can be overridden by the SelectedItemCssClass property
    	background-color: #404040;
        color: white;
      <Grid Name="ui-root" Rows="200px 1fr" Columns="auto 1fr" />
      <Model Name="Customer" Source="@Object[Customers].DbObjectName" Fields="ID,Name" />
    	<List Name="Customers" Source="@Object[Customers].DbObjectName" Fields="ID,Name"/>    	
  <UI Grid="ui-root">
    <Listbox Name="MyListbox" Row="1" 
    	SelectedValue="{Binding Path:Customer.ID}" />
Listbox using SelectedItemCssClass to apply a custom style to the selected item

$Ctrl keyword
The new $Ctrl keyword provides information about the current UI control, such as its Id. If you don’t specify a Name for the control, it will get an auto generated id. This feature is useful in ItemTemplates where you cannot use the Name property to identify the control. A typical use case is when you have dropdowns in a listbox, and you need to track the selection of each dropdown.

// Use $Ctrl.Id to pass the (auto generated) id of the control to the ItemSelected handler
<Dropdown ItemSelected="onItemSelected($Data, $Ctrl.Id)"/>        

Dynamic number of SplitButton sub items
The SplitButton control now supports dynamically adding and removing sub items (SplitButtonItems) based on data in a data source, for example a list. This enables having SplitButtons with a dynamic number of sub actions based on state in the Form Schema.

  	<Function Name="send">
  	<Function Name="onClick" Parameters="data">
  	<Function Name="filter" Parameters="items">
  		return items.filter(f => == 'a' || == 'b' );
  	<FormEventHandler On="Init">
  		this.addViewStateModel("Actions", {
  		 	   text: "Subaction 1",
	  		 	text: "Subaction 2",
  <UI Grid="grid">
  	<Grid Rows="auto 1fr" Columns="200px 200px 1fr">
  		<SplitButton Text="Send" ItemsSource="{Binding Path:ViewState.Actions.splitButtons}" ItemsSourceFilter="filter" Click="send">
  			<SplitButtonItemTemplate Text="{Binding Path:text}" Click="onClick($Data)"/>


  • The Lisbox, Dropdown and TreeView control now supports Grid as the ItemTemplate container
  • We added support for handling Unload of a Form Schema from the DOM. Developers can use this event to do various types of cleanup.

Work Process

Access control on Work Process contents
We have added an option to restrict access to Work Process contents to Process administrators only. This makes all Workbooks in the Work Process unavailable to users that are not Process Administrators, even though they have been granted access through the Workbook Permissions Manager. Note that Process Administrators must still be granted regular access through the Workbook Permissions Manager in addition to being a Process Administrator to get exclusive access.

Work Process Deleted event
Solution Developers can now subscribe to a “Work Process Deleted” event which is from the Work Process Editor component when a Work Process has been deleted. This enables performing actions after a Work Process has been deleted, such as custom cleanup.


  • The web application has been updated to React 18 and the latest npm libraries. The most notable effect for end users is that the cold start loading time is improved.
  • When exporting a Package, the package version is automatically added to the file name
  • Tab Control now has support for Large and Default modes. When using Large mode, the tabs are displayed with larger text.
  • Tab Control now has support for controlling whether or not borders should be displayed.
  • We added support for translations of dimension names. You can use a text code to use built-in translation system in InVision, or use the @Object[…].Lookup[] feature to roll your own.

Breaking changes

  • The Transaction Pipeline Producer will now include wildcard matches in addition to exact matches when resolving which transaction to generate from the rule set. This may cause more transactions to be generated from the Transaction Pipeline after upgrading to 2022.3 (depending on how the rule set table has been set up).
    See discussion here:

Happy dev-life from the dev team!