What changes from the original ProjectWise configuration model
This overview is for people who know ProjectWise administration, attributes, forms, and lookup Environments but do not necessarily know programming or CEL.
CEL is not a new database, a SQL client, or a universal ProjectWise API. It is a safe language for calculating a value from a predefined context.
What Bentley is actually restricting
The change concerns support for SQL expressions in ProjectWise Cloud attributes. Bentley is introducing the Prevent new SQL expressions in attributes setting.
In practice:
- new SQL attribute expressions cannot be created,
- changing an existing SQL attribute requires rebuilding it in PW CEL,
- existing SQL attributes are not deleted automatically and should continue to work until they need modification,
- Bentley currently provides no automatic converter that reliably recreates an old configuration in CEL.
This is not a blanket ban on everything used in older ProjectWise configurations. Those expressions commonly mixed at least three different things:
- ProjectWise system variables, such as the current user or another attribute value.
- SQL functions, such as
ISNULL,IIF, orCHARINDEX. - Actual database access, such as tables, views, joins, and stored procedures.
The first two groups can often be rewritten in CEL fairly directly. The third group is the main boundary: CEL does not receive unrestricted access to the SQL database.
What CEL is
CEL means Common Expression Language. ProjectWise uses its own host implementation, referred to here as PW CEL.
An expression receives permitted inputs, applies short logic, and returns a result. For example:
thisUser.nameThe result is the current user's name because ProjectWise placed the thisUser object in the context.
The key idea is that CEL knows nothing about the database by itself. It knows only what ProjectWise exposes at the current evaluation point.
Document Attributes can, for example, provide access to:
- the current form through
thisForm, - the current document through
thisDocument, - its folder through
thisFolder, - a Work Area through the corresponding object,
- the current user through
thisUser, - the current UTC time,
- registered lookups.
Another context, such as Workflow Rules Engine, can expose a different set of objects. An expression that works in one context is not automatically available everywhere.
The original model and PW CEL side by side
| Original configuration | PW CEL |
|---|---|
| An expression could mix ProjectWise variables, SQL functions, and database logic. | An expression uses CEL syntax and objects supplied by ProjectWise. |
| Administrators often needed table, column, view, or procedure names. | The internal database schema is not part of the supported interface. |
| SQL could join and read data from different tables. | CEL works with the active context and registered lookups. |
| Logic could be tightly coupled to the database and a product version. | Bentley controls the published objects, functions, and datasets. |
| A schema change or cloud restriction could break the expression. | Database separation gives Bentley a more stable and safer boundary. |
| Much of the control belonged to the database administrator. | More control now sits in lookup registration and the supported PW CEL API. |
The most important limitations
This does not mean Bentley could never expose more data. The vendor could add another controlled object or lookup dataset. Administrators, however, cannot declare an arbitrary SQL table as CEL input. A supported object, registered lookup, or external synchronization must be used.
Which tables can be used
ProjectWise Administrator 2026 documents these eight built-in lookups:
| Built-in lookup | Selectable columns | Required filter | Contents |
|---|---|---|---|
DMS.Users | name, description, email | — | Datasource users |
DMS.UserLists | name, description | — | User lists |
DMS.UsersInList | name, description, email | list | Users in one list |
DMS.UserGroups | name, description | — | User groups |
DMS.UsersInGroup | name, description, email | group | Users in one group |
DMS.Workflows | name, description | — | Workflow definitions |
DMS.States | name, description | — | Datasource states |
DMS.StatesInWorkflow | name, description | workflow | States in one workflow |
The list, group, and workflow columns are used for filtering. They are not ordinary return columns.
The DMS. prefix is reserved for ProjectWise built-in lookups and should not be used for a custom lookup.
This list does not include documents, folders, or arbitrary Environment tables. The current document and folder are accessed through context objects. Environment data is exposed through a separately registered Environment lookup.
Three lookup types
1. Environment lookup
An Environment lookup uses documents in a selected ProjectWise Environment as lookup rows. Its registration defines:
- the source Environment,
- the attributes exposed as columns,
- the value and description columns,
- optional fixed filters and sorting.
This is the closest replacement for a legacy lookup Environment. The Environment's existence alone is not sufficient. CEL can use it only after a CEL lookup has been registered over it.
Two details still matter:
- CEL sees only attributes exposed by the lookup definition.
- If a new attribute is later added to the Environment, update the lookup definition and, according to Bentley documentation, reopen and save expressions that need to use the new attribute.
Basic usage:
getLookup('Lkp.Originator')
.filterEquals('PW_CODE', thisForm.FI_ORIGIN_CODE)
.selectOne('PW_DESCRIPTION', '')The expression gets a registered lookup, keeps records with a matching code, and returns one description. If it does not find exactly one record, it returns an empty string.
2. Standard lookup
A Standard lookup is a ProjectWise-managed data table populated through a supported PowerShell or SDK process. It is suitable for ERP, CRM, or other external data.
It is not automatically a live SQL query. It is a controlled copy or snapshot. When the source system changes, the rows must be uploaded or synchronized again.
3. Built-in lookup
A Built-in lookup is supplied by ProjectWise. This category contains the exact eight DMS.* datasets listed above. ProjectWise manages their contents, and CEL uses only the documented columns and filters.
How a lookup is read
The basic process has three steps:
getLookup('Name')selects a registered lookup.filterEquals(...),filterIn(...), and similar functions narrow its rows.select(...)orselectOne(...)requests the result.
Supported operations include:
getLookup,listLookups,filterEquals,filterNotEquals,filterContains,filterNotContains,filterIn,filterNotIn,select,selectOne.
Filter large lookups as early as possible and select only afterward. selectOne without a fallback expects exactly one record; zero or multiple matches cause an error. With a fallback, both cases return the fallback value.
Example using a built-in lookup:
getLookup('DMS.Users')
.filterEquals('name', thisForm.PW_USERNAME)
.selectOne('description', '')The expression finds a user by login name and returns the description used as the readable full name in this configuration.
Simple examples
Another attribute on the current form
An older ProjectWise expression could use a system variable such as $EDIT#Discipline$. PW CEL uses the form object:
thisForm.DisciplineA condition instead of IIF
thisForm.TRIG_MINOR_REV == '1' ? thisForm.RV_REV_1 : ''If the trigger is 1, the expression returns the revision. Otherwise it returns an empty string.
A value based on the current user
getLookup('Lkp.UserSupl')
.filterEquals('PW_USERNAME', thisUser.name)
.selectOne('PW_ORIGINATOR_CODE', '')CEL gets the current login name, finds it in a registered lookup, and returns the assigned organization code.
Can another Environment be read?
Not directly through the form context. thisForm represents the current form, and there is no general command to open any Environment and read its rows.
For an older Environment used as a code list, the recommended model is:
- Keep the Environment as the place where values are managed.
- Register an Environment lookup over selected Environment attributes.
- Read, filter, and select it in CEL through
getLookup(...).
If the source data is not held in a suitable Environment, use a synchronized Standard lookup. Complex relational logic across multiple tables usually belongs outside CEL: precompute the result and expose prepared data to the expression.
What to use in each situation
| Need | First candidate |
|---|---|
| Current user | thisUser |
| Value on the current form | thisForm |
| Current document, folder, or Work Area | Corresponding PW CEL object |
| Code list managed in a ProjectWise Environment | Environment lookup |
| Users, groups, lists, workflows, and states | Built-in DMS.* lookup |
| ERP, CRM, or other external data | Standard lookup with managed synchronization |
| Reusable CEL logic | Library Expression |
| Complex database join, aggregation, or procedure | Redesign, precomputation, or external integration |
A Library Expression stores reusable CEL logic below lib and allows multiple expressions to call it. It is not a path to the database and does not expand CEL data permissions.
How to approach migration
For each old attribute, first determine what it actually does:
- Does it read only the current user, document, folder, or another attribute?
- Does it use only a simple condition or text operation?
- Does it read a code list from a legacy lookup Environment?
- Does it join data from multiple tables?
- Does it call a stored procedure?
- Does it return one value or build a selection list?
- What happens with zero, one, and multiple results?
Then choose the target:
- a context object for data in the current PW context,
- a CEL operation for conditions, text, lists, or time,
- an Environment lookup for a ProjectWise-managed code list,
- a Built-in lookup for supported system data,
- a Standard lookup for external data,
- a redesign when the old solution depends on arbitrary SQL or a procedure.
Common misunderstandings
Is CEL a replacement for SQL?
Not in full. It replaces expression logic for supported ProjectWise scenarios, not general database querying.
Are DMS.Users and the other names SQL tables?
Not to a CEL user. They are built-in lookup datasets with exact columns and filters.
Can I use any SQL table if I know its name?
No. A database table name is not a supported CEL interface.
Can values still be read from a legacy lookup Environment?
Yes, after an Environment lookup is registered over it and the required attributes are exposed. It is not read through an arbitrary direct query.
Must an Environment lookup be rebuilt after every new record?
No. Rows are read dynamically from the source Environment. Update the definition when exposed columns or lookup configuration change.
Is a Standard lookup dynamic?
Not in the same way. Its rows must be uploaded or synchronized through a supported tool.
Can Bentley expose more data in the future?
Yes. Bentley can add supported objects or datasets. That does not allow today's administrator to open an arbitrary table.
Conclusion
PW CEL changes the starting question:
- before, administrators often asked “where is this value in the database?”,
- now they must ask “which supported object or lookup exposes this value?”.
Simple calculations, conditions, text processing, and work with the current document can be handled directly in CEL. Code lists are handled through lookups. Arbitrary database logic is not translated directly into CEL; it must be replaced by a supported data flow or redesigned.
That is both the main benefit and limitation of PW CEL: it is safer and more controlled, but deliberately does not provide the freedom of general SQL.
Official sources
The explanations and examples are based on public Bentley documentation for ProjectWise Administrator 2026 and real PW CEL usage patterns.
- SQL Attribute Support changes – Moving to CEL
- ProjectWise CEL documentation
- CEL Contexts
- ProjectWise CEL Objects
- ProjectWise CEL Lookups
- List of Built-in Lookups
- Lookup Functions
- Replacing SQL Attribute System Variables
- Replacing Built-in SQL Functions
- Library Expressions
Sources checked: 18 August 2026.