Skip to content

プロセス志向経営管理の実践ツール
トータルBPMエンジン・SPACシリーズとは

Mr Kenji Yoshihara
CEO of NIX System Laboratory Corp
よしはら・けんじ
日本能率協会システム技術部長、コンピュータ事業部長、ジェー・エム・エー・システムズ専務を経て、1987 年に (株) Nix システム研究所を創設。日本システミックス代表取締役。長く BPM の普及活動を行う。
Kenji Yoshihara

忘れ去られたビジネスプロセス

図1「ビジネスプロセス、失われた20年」は過去50年のIT化基本アプローチの変遷を描いたものである。
図1 ビジネスプロセス、失われた20年

この50年のビジネス情報システム構築方法の進化過程を振り返ると、最初のアプローチは人の業務プロセスをコンピュータに置換する方法が中心であった。いわゆる、POA(プロセス中心アプローチ)である。この時代が30年続いて1970年代後半に、データの重複ファイルを統合する、DOA(データ中心アプローチ)が始まった。
それからの20年間、人のプロセスは情報システムに主導権を奪われ続け、その結果プロセスの流れは見えなくなっていったのである。この「見えない化」の進行は、とりも直さず、DOAの進歩と継続的POA管理の放棄に起因するものである。DOAなくして情報システムの発展はあり得なかったけれども、POAなくして人はいまのプロセスをガバナンスできないのである。筆者は10年前、「ビジネスプロセス、失われた20年」の図を示してPOAの復権を訴え、BPOA(ビジネスプロセス中心アプローチ)を提唱したが、当時は絵空事に思う人が大半であった。

経営管理方式のへ影響

その一方で、この20年のビジネスIT化の進行もあって、旧来のビジネススタイルは創造的破壊の渦に巻き込まれていった。1980年代後半以降、部門間プロセスがIT化され始め、ビジネススタイルの変化に次ぐ変革がビジネス経営管理を揺さぶるようになった。その結果として従来型の業務機能分担組織型管理方式は機能しなくなり、組織を超えたプロセス管理に移行せざるを得ない事態に遭遇することになる。
 さらに、1990年代半ばからは、IT主導のネットワークビジネス分業型経営の到来は、さまざまな企業統合と融合をもたらしつつある。その典型は、サプライチェーン・マネジメント志向経営である。M&A、事業提携、相互乗り入れ、そしてアウトソーシング志向経営はプロセス管理なくして成立しなくなっている。
 今日、すべてのビジネスはITプロセスと人のプロセスの入れ子状態となり、人中心の業務機能分担組織管理方式のみでは、企業管理は麻痺寸前である。この流れの中で、人とITプロセスを一体的に可視化する「ビジネスプロセス・マネジメント」(BPM)が着目されている。そして、プロセスオーナーによるビジネスプロセス統治・分担組織管理と従来型の業務機能分担組織管理方式のハイブリッド経営管理への移行が始まろうとしている。
 しかしながら、ビジネスプロセス統治分担組織管理方式の体系的方法論は存在しない。こうした中で、BPM方法論を世に送り出すことは、これからの経営管理にとって強力な武器となろう。

BPMとは何か?

POAの復権とBPM時代到来の背景について述べきた。ここで筆者が考えるBPMを定義しておこう。
 「BPMの本流はビジネス実行プロセス全体を対象とした、人とモノと情報の複合的なプロセスフロー化に基づき、各階層プロセスの機能とそのfrom/toを正しく把握定義して、ビジネスプロセスの現状マップを維持管理することである。そしてプロセスの改善にチャレンジして、より優れたプロセスへの進化に努めることである」
 最近ではSOAや自動プログラミングによるIT化プロセスの管理を、BPMと呼ぶことがあるが、紛らわしいので筆者はそれらを区別して使うことが望ましいと考える。いずれにせよ、BPMの基本はあくまでも、As-Isプロセスステータスの把握と、その管理にある。
 ここで重要なキーワードはプロセス階層体系である。これを粒度という人もいる。筆者は縮尺度と呼ぶ。縮尺の異なる地図はつながらないことは自明のことであるが、ビジネスプロセスでは往々にして大小プロセスが混在したプロセスマップが横行していて、整理体系もないまま、管理のすべもないので、いつしか打ち捨てられている。
 筆者はプロセスの縮尺体系をH・BPM(ヒューマンBPM)で6階層、IT・BPMを3階層体系で考えている。以下にそれを図示する。
図3 BPMの階層構造ビュー

BPMで何ができ、何が変わるのか?

再三述べてきたことであるが、BPMの目的は「ビジネスプロセスの可視化を実現すること」にある。

    • BPM(SPAC)は、ネットワーク型経営におけるビジネスガバナンス(統治)のツールであり、ガバナンスは実態の可視化から始まる!
    • ガバナンス(統治)とは、統治客体の活動実態を可視化に置き、望ましい方向に誘導し、コントロールすることである
    • そのためには、統治客体の活動実態(As-Is)を把握し、可視化することが大前提となる
    • 今が見えれば、初めて望ましい状態(To-Be)を洞察・発見して、As-IsからTo-Beへの移行を実行できる
    • As-Isの可視化なしには経営のガバナンスは機能し得ない

とはいえど、方法論なきBPMも機能し得ない。何のために体系的BPM方法論が必要なのかを考えてみてほしい。例えば、目的事象をあるがままに識別して、実態を投影できないプロセス化では、実態を管理することはできない。目的事象を識別できないとか、実態と異なるドライブマップが使いものにはならないことと同様である。

SPAC方法論とは

最後に筆者が提案しているBPM方法論「SPAC」(エスパック)を紹介しておく。SPACとはSystem Process Architecture Complexの略称である。その機能と特徴は、リアルプロセスとバーチャルプロセスのハイブリッドなプロセスフローを6階層で体系的に表示する。そして単位プロセスユニットごとにI/Oとその処理機能(ルール)ならびにタイムフレーム、工数、良品率などのプロセス性能の定義登録、保存、参照、再利用ができる。
 このマニュアル体系はSPAC 0、Ⅰ、Ⅱの3部作である。0はAs-Is分析管理方法論であり、IはTo-Be設計管理方法論である。ⅡはⅠを実行する時の基本手法解説編である。
 プロセスの登録は、同一レベルのプロセスフローについて複数のAs-Is及びAs-Ifと複数のTo-Be開発サイクルをサポートする。この適用対象は複数存在するが、いかようなプロセス管理目的であっても適用できる。その1つとして昨今、企業において準備されているSOX法・内部統制対応のリスクプロセス文書化への適用と経営効率管理対応のプロセス管理へのマルチ適用が挙げられよう。

H・BPMとIT・BPMのドッキング

当然ながら、SPAC方法論の実践プロセスは、情報システムとして運用される。このツールは、SPACナビ10と呼び、Avantage ActiveModelerをプラットホームとして、構築された。SPACナビ10の利用により、新プロセスマッピングとその定義作業の生産性のみならず、プロセス設計と定義とそのメンテナンスの飛躍的なスピードアップが実現した。
 もう一つのBPM実践におけるSPACナビ10の役割と意義は,SPACナビ10が、H・BPMとIT・BPMの架け橋となったことである。SPACナビ10のカバーするBPM階層レベルの範囲は、人が主体のH・BPMの6階層である。そして、SPACナビ10のH・BPM第6レベルで、Avantage ActiveFlowに連携し、IT・BPMに連動することになる。ここに、初めて人とITのトータルBPMが完成することになった。その意義は、プロセス志向経営管理にとって一つの突破口になると思う。

筆者プロフィール

吉原 賢治(よしはら けんじ)
株式会社Nixシステム研究所 代表取締役、
主な著書に「日本型サプライチェーン経営への挑戦」(日本プラントメンテナンス協会)共著、「生産管理の事典」(朝倉書店)共著(サプライチェーンの章担当)、「ビジネスモデル入門」(工業調査会)がある。

Process Metrics and going to the Bank$$$…

A key design concept of ActiveModeler Avantage is “extensibility”. That is the ability to build on a basic process diagram (or drawing) and add more important information to it, so detailed knowledge of the process can be built up.

A key limitation of many process diagrams made with flowchart software is the fact that they are just drawings and information such as:

  • What resources do the activities consume, how much do they cost?
  • What are the Value Adding (VA) and Non-Value Adding (NVA) activities in the process?

To take a very simple example, I’ve just returned from the bank and what a frustrating time it was - it took most of the morning. Let’s have a look at the process diagram to find out more:

Banking process

This looks OK and straightforward but there is no indication here of how long I waited and no analysis of why I was frustrated. All activities look the same and are of equal importance.

Avantage allows you to click on each activity and add times and costs to them like this:

Adding costs

Here I added 30 minutes for the travel to the bank and $4 for the fixed cost of getting there by subway.

Waiting to be processed was frustrating; there was a very long line as it was the end of the month and a Friday - I spent 20 minutes waiting. Submitting the transaction was easy and took only about 2 minutes. However it cost $40 for the funds transfer.
As for the other activities:

  • Process transaction (by the bank staff member) – 5 minutes.
  • Check transaction by me – 1 minute.
  • Travelling back home – another 30 minutes and another $4.

Already you can see we are building up more information about the trip to the bank. Avantage allows you to add information for each activity and then run an analysis report.

Now I consider also that my time is valuable and I would like to cost it in. I can set it at $5,000 per month for this type of work which could equate to an accounting supervisor rate for example.

I can go to the organization structure and set this very easily. This is also something a flowchart program does not have.

Adding a cost rate

I can add in what my working regime is as well:

Setting working regime

Now my time is also costed in.

Time costed in

You can see this simple bank transaction is started to look quite expensive. You can imagine for a business, this cost is very important.
Even looking at the Travel to the Bank cost:
As my charge rate is $5,000 per 145 hours ($34.48/hour)
The 30 minutes cost is $17.24
Adding in the $4 subway cost – the cost of this activity is $21.24

Avantage allows you to run an analysis report to see the total times and costs for all the activities.
This is conveniently presented to you in Excel.

Costs report

You can see the total times and costs of this bank trip at the bottom of the report.
It is a staggering $95.70 for me the customer. The total cost of the process is $98.57 but that includes the $2.87 bank internal costs for collection of the transfer information. We do not include the bank actual processing costs here as they are not in our scope.

I will just highlight the keys areas of this Excel sheet again:

Cost highlight

Yes – it is $95.70! How to improve this figure - Well we can consider using Internet banking as much as possible to save these costs. In fact, we can draw an “As-is” and “To-be” process diagram. You can show the cost savings clearly on two Excel sheets so it is easy to get buy-in to your ideas.

Let’s now take this one step further and talk of categories.

Categorization allows you to colour code the activities to your preference. You might what to highlight VA and NVA activities for example.
The choice of this categorization is up to you – Avantage allows you to define this and also allows multiple category sets so you can look at the process model from difference perspectives and colours.

This is the Category designer and you can see a typical Category set here:

Category editor

This is another more detailed one:

Detail of category editor

Let’s apply the first one to our process map:

Applying categories

Here it is:

Categorized process diagram

Now finally we can do a full analysis including the categories again in Excel

Categorized report

And we could even use the Excel Pivot table to do really detailed analysis, like the cost of a category for a department within a company for example e.g. communication costs or wait time costs per department.

Pivot

Summary

I hope this has given you a useful introduction into the use of metrics for a process map. You can see that we have come a long way even in this short article from the simple flowchart. I am sure Avantage can help your business to become most cost effective and competitive in a simple to use way.

Technorati Tags: , , , ,

How to license a plugin

You will receive an email containing your license key. This document explains how to install the license key.

Install the plugin

1 Quit Avantage
2 Run the plugin installer
3 Start Avantage
4 Choose the Help>About menu and restart Avantage at completion.

The Help>About> License Info tab

The Help>About>License Info tab

Locate the plugin you want to license from the displayed list of installed plugins. Select it by clicking on it then click on the Enter key button.

Enter the license key you received from KAISHA-Tec

Enter license key

After sucessful license installation the license info of your plugin is updated.

after_license_key1.png

Restart Avantage

The final step is to restart Avantage. Upon startup the plugin will be fully licensed.

How to register your Avantage

In order to enable the full functionality of Avantage's process modeling it is necessary to register the software. For home users this is at no cost. Please read this for the definition of a home user.

If this is the first time that you have installed Avantage then you will be automatically prompted to register the software.

If you have updated from an earlier version of Avantage, you must also register the updated version but you are not prompted to do so. In this case use the Help>Register menu instead.

Registering with the Help>Register menu

Register menu

Restart Avantage after the registration is done

It is necessary to restart Avantage after registering. When you restart Avantage all restrictions are removed.

Modeling real world organization structures with BPMN

In BPMN 1.0 little attention was paid to modeling organization structures since the concept of pools and lanes was adequate for most process execution modeling. At first consideration, this seems to be a serious weakness - but is it?.

Being able to describe real world organization structures is essential for Financial/commercial/business modeling where it is required to model costs by department, sub departments and roles.

Real world human organizational structures are hierarchical, BPMN pools and lanes cannot directly express these hierarchies because of the limited scope for nesting these objects in a diagram.

The problem is easily solved if pools and lanes are instead treated as references (sign posts) to organization information managed elsewhere. This is what the Avantage Organization plugin does and it is completely transparent to the BPMN process model because it runs side by side with the BPMN model. Organization modeling is a standard feature of the FREE Avantage BPM Foundation.

A typical organization structure

The example here is pretty typical, the image describes a manufacturing department within a larger organization tree (only the manufacturing department is expanded and visible). Within departments there can be sub-departments (with as many levels as required). Within any department there can occur Roles. Roles represent different classes of workers, machines or robots.

The Avantage Organization plugin implements the ActiveFlow Organization model. The ActiveFlow Organization model also allows for the definition of Candidates (actual employees who are qualified to be assigned to Roles). If you are interested in creating executable BPMN diagrams and are technically competent with IIS, ASP and SQL Server deployments then you might like to download the Avantage ActiveFlow Designer and take it for a test drive.

Manufacturing department

Organization hierarchy

Organizational objects are not saved in the BPMN process model, they are saved in separate .organization files in your project workspace. There can only be one organization file active per project, this organization file is known as the Project Default organization file. The default organization file's structure applies to all process models in a project. What this means is that you can switch in and out different organization structures simply by changing the project default organization file in the modeler's workspace - this is very powerful.

The icon of the default organization file in a project is displayed with a tick image overlay
Default organization file

By right-clicking on a pool or lane you can select the Join:Organization menu action.

Link pool or lane to organization unit

This displays the organization unit chooser dialog. After you make your selection you will notice that the label of the pool/lane in the diagram is changed, it is prefixed with ">" and adopts the node path of the organization unit you just linked to.
Link to orgunit dialog

After you have linked your BPMN lane and pool objects up to organization units, conceptually your process model is now like the image below.
Organization structure and BPMN

Going on to costing

The Avantage Analytics Plugin lets you assign costing information to departments and roles, this enables the plugin to calculate the cost of activities performed by the department or role and it is completely BPMN compliant. If you are interested in metrical analysis of process models and would like to learn more about the Analytics Plugin then you can download a trial version from here Download Process Analytics installer (3.5MB)

Organization unit costing

Running a startup script

It easy to have Avantage run a script on startup. This script can be used as a bootstrap loader to load other scripts, each providing different extensions

This article explains how you can arrange for a script to automatically start whenever your Avantage BPM Foundation starts in three simple steps. Scripts launched this way run in their own threads independently of the UI thread.

Step 1: Make sure that the Lua plugin is set to be loaded at startup

Choose the File:Preferences menu and then select the General section. Make sure that the plugin KT.AM.Lua is checked ON

Startup plugin settings

Step 2: Specify the script to be started

Next you need to click on the Lua plugin's entry and set Execute default script on startup to True and then click on the elipsis in the Startup lua script property to choose the script file to execute.

Lua plugin settings

Step 3: Quit and restart

This will ensure that the Lua plugin is loaded and the script is executed. Any errors encountered in the script are logged in the Log View.

Import your Excel flowcharts into BPMN

The popularity of Excel and the ease with which you can insert graphical flow chart shapes into worksheets has ensured that there are a great many spreadsheets with embedded flowcharts in existence. It is possible extract this information into a BPMN process model

This article explains how you can import graphical flow charts embedded in Excel worksheets into BPMN process diagrams

Let's do a Google search for Excel flowchart and see where that takes us... to the Journal of Accountancy Online where the article expounds the virtues of Excel for process modeling. This is what the BPM world is up against. A sea of Excel spreadsheets doesn't quite stack up as a process model in these days of standardization.

Luckily it is easy these days to convert these charts straight into BPMN.

What you need to get started

  1. ActiveModeler Avantage BPM Foundation
    Download the ActiveModeler Avantage BPM Foundation installer from here [14MB]
  2. The Import.Excel.AutoShapes plugin
    Download the plugin from here [2MB]
  3. Excel (Office 2001 or later) must be already installed on your computer

Install the Avantage BPM Foundation first, and then install the Import.Excel.AutoShapes plugin. Start Avantage and you are ready to go.

A typical Excel flow diagram

excel_flowchart.png

Excel flowcharts commonly use vertical lines to specify divisions of domain. The converter will create swimlanes for these divisions

How to import it

Create a project

Avantage organises your work into projects. Projects contain related files (like process models, categories, organisations, etc). To create a new project choose the New project.. menu from the File menu. New project menu

Enter the name of your new project into the new project dialog. Don't change the location - just provide a name. Project dialog

After you have done this your workspace navigator should look like this:
Workspace with excel project

Create a process model to contain the diagrams

Right-click on your freshly minted Excel project and choose the New:Process model file... action. New model action

Expand the new process model, it will look like this:
Empty model
The nodes in the tree named Processes, As is, Automated and To be are what we call MeasurePoints.

Run the convertor

Right-click on a measurepoint that is to become the parent of the imported diagram and choose the Import diagram from Excel worksheet... action. You are prompted to choose a file or selection of files to convert.

The converted diagram is added at the measurepoint you selected. You can explore its structure by clicking on the diagram's + sign or you can open it in the diagram editor by double-clicking it.

Excel import actionchoose_xls_dialog.png

Geometric layout of converted BPMN diagram

X and Y coordinate information from the Excel flowchart is discarded by the convertor and instead it relies on the Diagram Editor to perform a once only automatic layout the first time the diagram is opened. You can then edit the diagram manually and change the layout/routing of connections as necessary.imported_bpmn_diagram.png

Custom post-conversion processing

You can tell the reader plugin to execute a Lua script at the completion of the conversion. This makes it possible to scrape other information from the worksheet that may be relevant to the process model you are creating. For example, the worksheet might contain metrics (volumes, costs etc) and a post-conversion script could read this information and write it into the process model.

How to specify a default post-conversion script

A prototype (template) script is provided in the Import.Excel.AutoShapes plugin folder. It is named afterconversion.lua. You can add this file to your working project with the Add existing Lua file... context menu (a copy of this file will be added into your project). The file should now be displayed in the project's sub-tree. Right-click on it and choose the "Set as default post conversion script" menu action. This will make this file the new default .lua file which runs post-conversion. To turn the default off, right-click on the file again and choose the "Remove as default post conversion script" menu action.
You can easily see which script is the default post conversion for a project because its icon is overlayed with a tick mark like the image below.
post_conversion_default.png

Passed in parameters

The script receives a Convertor object and a Progressmonitor object.

The Convertor object

The Convertor object contains a reference to the conversion context.
convertor_members2.png

Excel

This is a reference to a simplified .NET Excel wrapper.

InsertionPoint

This is the BPObject which represents the point in the BPMNTree where the Diagram is to be inserted. It is usually a BPD_MeasurePoint type object.

Project

This is the Avantage project in which the action is taking place.

Diagram

This is the BPD_Diagram object that was created by the convertor.

The ExcelHelper object

The ExcelHelper holds references to the .NET interop that is managing the Excel COM instance.
excelhelper_members.png

Changing autoshape BPMN conversion rules

You can change BPMN shape lookup tables using a table editor. Operate the drop-down menu in the BPMN column to select the BPMN object to be created. NullShape is a special do nothing shape.

Importing metrics and documentation references

A spreadheet is likely to contain numerical data which is sometimes associated with flow objects, for example costs may be assigned to various activities. To do this you will need to purchase the Avantage Analytics Plugin pack. (See Analytics Pack for more details). The Analytics Pack provides a business metrics DFD mixin for BPMN diagrams.


Appendix A: Post-conversion stub script

---
--- This script is called after the Excel Autoshape conversion has converted the Excel shapes collection
--- into BPMN.   It is an afterburner type script template which can be used to perform custom
--- post processing of the Excel workbook after the BPMN model has been created.
---
 
luanet.load_assembly("Microsoft.Office.Interop.Excel")
Range = luanet.import_type("Microsoft.Office.Interop.Excel.Range")
MessageBox = luanet.System.Windows.Forms.MessageBox
 
--- There are two variables defined by the plugin just before it calls this script.
---	1. Monitor which is an IProgressMonitor object
---	2. Convertor which is a KT.AM.Import.Excel.AutoShapes.ToBPMN convertor object. This contains a reference
---	to the Excel instance being worked with, it also provides the BPMNTree output context for the conversion.
 
--- This is how to update the progress display during a repetitive operation
for i = 0, 3000, 1 do
	Monitor.SubTaskName = "Script loop " .. i
	--- Do something
end
return 0

Scripting a .NET BPMN process model with Lua - Part 2

This article is the second in a series of hands-on articles which will show you how to access the resources within your process model by scripting. Part 1 showed how to add custom context menus to objects displayed in Avantage's UI. This example extends on this to provide some contribution actions which add custom BPMN properties to a selected BPMN object in the UI.

Properties are a bit like Post-It Notes. You scribble a note, tear off a leaf and stick it onto something and the tag stays on the host until it is removed. Property objects can be used to 'stick' data items to host BPMN objects. Instead of glue, the property is put in a Properties collection and becomes a part of the bundle of information that is associated with the host object.

What are they useful for?

Imagine that you have an existing process model, and that due to a change of company policy it is necessary to bind new information into that model. This is where Property objects can be used. You could define a string property to act as a container for arbitrary Xml describing the information.

BPMN Property objects

Properties occur within BPMN objects as a collection (0-n) with the name Properties. Below is the definition for a BPMN Property object. The (0-n) notation means that the collection can hold none or any number of properties, its use is optional.

Property specification

BPMN/.NET Property mapping

The BPMN Property is implemented in Avantage by the BPD_Property class. The range of types the property can be is the standard set of .NET CLR value types. The type of the property is determined automatically by the type of the Value you assign to it.

Inspecting property
Because all BPMN objects in Avantage derive from BPObjects, BPD_Property inherit the standard BPObject attributes like ParentID, ID, Description and Documentation. These are of no consequence to BPMN compatibility. The IsXPDLDataField attribute determines whether the property is visible to the XPDL 2.0 plugin or not. Whether any BPObject is visible in the process model navigator is determined by the VisibleInTree attribute.

Creating a property

In order to create a property we use a statement like this:

 newProperty = BPD_Property()

The variable newProperty holds a freshly created property that is not connected in any way to the process model. It has a default Name and ID and contains a default string value type.
In order to define the final value type of our property, all that is necessary is to asssign its Value attribute a value of the desired type. Here our property is going to become a floating point type.

 newProperty.Name = "MyFloatProperty"
 newProperty.Value = 4.57e-3

Inserting the property into its host object

After the property has been created, the next step is to attach it to its host object so that it becomes a part of the model, and can be persisted when the model file is saved and opened. The Avantage process model is hierarchical where each object is contained by a higher level parent object. In this example, we have coded a Lua function that wraps this operation.

function InsertInModel(ownerObject, propertyObject)
	propertyObject:SetParentEx(ownerObject)
	FireModifyEvent(ownerObject, true)
end

This function accepts two parameters, ownerObject which is the BPObject which is to become the parent and propertyObject which is the child. The process model workhorse function SetParentEx(owner) does this. The SetParentEx() method is present on all process model objects.
Finally, it is necessary to advise the process model that modifications have been made. This allows any listeners to become aware of the change. Some common listeners to a process model are the Navigator, the Diagram Editor and the Property Inspector.

 FireModifyEvent(objectModified, IsFinalNotification)

The IsFinalNotification parameter is a bool type which indicates if this is the last modification or not. When this parameter is false, the notification is just enqueued for later. When the parameter is true, any enqueued notifications are sent before the current notification is sent. This is a performance optimisation to minimise notifications.

Accessing a property object programmatically

Properties (and all other BPObject collections in Avantage) implement the .NET IDictionary interface. When writing code in C# or VB.NET you can treat the collection with array semantics [index] however from Lua you cannot do this, so there are two general purpose Lua functions GetDictionaryEntry and SetDictionaryEntry which do the same thing.

Setting an existing property's value

SetDictionaryEntry(IDictionary dict, object key, object value)

dict is the collection to be accessed, and key is the key or index. Usually the key is string ID. value is the entry to be put into the collection. In the example snippet below, we use SetDictionaryEntry() to update a DateTime property called "RejectionDate".

SetDictionaryEntry(selectedBPDBase.Properties, "RejectionDate", DateTime.UtcNow)

Don't use this function to initially add a new property to a process model, this must be done with the BPObject.SetParentEx() method. If you add a property using SetDictionaryEntry() it will not persist and will not be correctly registered in the model.

Getting an entry

 object GetDictionaryEntry(IDictionary dict, object key)

dict is the collection to be accessed, and key is the key or index. Usually the key is string ID.

 aProperty = GetDictionaryEntry(selectedBPDBase.Properties, newname)
 if (aProperty ~= nil) then
	MessageBox:Show("Found the property!" .. Environment.NewLine .. "Name=" .. aProperty.Name .. Environment.NewLine .. "Value = " .. aProperty.Value .. Environment.NewLine .. "Type=" .. aProperty.ValueType:ToString())
 end

--- This script demonstrates how to use BPMN Property objects to store custom information
--- within your process model.  
 
MessageBox = luanet.System.Windows.Forms.MessageBox
 
--- We are going to instantiate Property objects directly, so we need to import its class so that we can call its constructor
BPD_Property = luanet.KT.AM.Core.Resources.ProcessModel.BPObjects.BPMN.Property.BPD_Property
 
--- This function parents the property and then notifies the process model that the owner has been changed
--- this will in turn cause the Navigator and other views to refresh and the model file will be flagged as "Dirty"
--- which in turn enables the File save menu action
 
function InsertInModel(ownerObject, propertyObject)
	propertyObject:SetParentEx(ownerObject)
	FireModifyEvent(ownerObject, true)
end
 
--- This adds a custom floating point property object to the selected BPD_Base object
function DoAddFloatProperty(selectedBPDBase)
	if (selectedBPDBase ~= nil) then
		newProperty = BPD_Property() ---  This makes a new property by invoking the default constructor for BPD_Property
		newname = "Lua FLOAT " .. newProperty.Name
		newProperty.Name = newname
		newProperty.Value = 4.57e-3
		InsertInModel(selectedBPDBase, newProperty)
	end
end
 
--- This adds a custom string property object to the selected BPD_Base object
function DoAddStringProperty(selectedBPDBase)
	if (selectedBPDBase ~= nil) then
		newProperty = BPD_Property() ---  This makes a new property by invoking the default constructor for BPD_Property
		newname = "Lua STRING " .. newProperty.Name -- prepend something onto the automatically generated property name
		newProperty.Name = newname
		newProperty.Value = newProperty.Name .. ": The Antechinus stuartii sat quietly on the bookshelf nibbling on Fundamental Algorithms. He was so busy he didn't see the python who was hiding behind the next book"
		InsertInModel(selectedBPDBase, newProperty)
	end
end
 
--- This adds a custom bool property object to the selected BPD_Base object
function DoAddBoolProperty(selectedBPDBase)
	if (selectedBPDBase ~= nil) then
		newProperty = BPD_Property() ---  This makes a new property by invoking the default constructor for BPD_Property
		newname = "Lua BOOL " .. newProperty.Name
		newProperty.Name = newname
		newProperty.Value = true
		InsertInModel(selectedBPDBase, newProperty)
	end
end
 
--- delegate
function AddBoolPropertyMenuClicked(sender, args)
	if (args ~= nil) then
		DoAddBoolProperty(args.selectedObject)
	end
end
 
--- delegate
function AddStringPropertyMenuClicked(sender, args)
	if (args ~= nil) then
		DoAddStringProperty(args.selectedObject)
	end
end
 
--- delegate
function AddFloatPropertyMenuClicked(sender, args)
	if (args ~= nil) then
		DoAddFloatProperty(args.selectedObject)
	end
end
 
--- delegate
function UnloadExample(sender, args)
	MessageBox:Show("The custom property example script is now terminated")
	Terminate()
end
 
--- Create the menus which contribute to BPD_Base. All BPMN objects except for BPD_Property derive from BPD_Base. So these
--- menus will be displayed when the user right-clicks on any BPMN object.
 
addStringProperty = ObjectPopup("KT.AM.Core.Resources.ProcessModel.BPObjects.BPMN.BPD_Base", "Add STRING property", "AddStringProperty", "Add a custom BPD_Property to selected object")
addStringProperty.Action:SetIcon("BPIcons", "Property");
handler = addStringProperty.Action:OnRun(AddStringPropertyMenuClicked);
 
addBoolProperty = ObjectPopup("KT.AM.Core.Resources.ProcessModel.BPObjects.BPMN.BPD_Base", "Add BOOL property", "AddBoolProperty", "Add a custom BPD_Property to selected object")
addBoolProperty.Action:SetIcon("BPIcons", "Property");
addBoolProperty.Action:OnRun(AddBoolPropertyMenuClicked);
 
addFloatProperty = ObjectPopup("KT.AM.Core.Resources.ProcessModel.BPObjects.BPMN.BPD_Base", "Add FLOAT property", "AddFloatProperty", "Add a custom BPD_Property to selected object")
addFloatProperty.Action:SetIcon("BPIcons", "Property");
addFloatProperty.Action:OnRun(AddFloatPropertyMenuClicked);
 
unload = ObjectPopup("KT.AM.Core.Resources.ProcessModel.BPObjects.BPMN.BPD_Base", "Unload custom property thread", "UnloadAddProperty", "Unload custom property script")
unload.Action:OnRun(UnloadExample)
 
--- This script thread will now sleep fitfully forever if there are contributions defined. To force unloading when you have contributions
--  you must call Terminate().
 

Scripting a .NET BPMN process model with Lua - Part 1

This article is the first in a series of hands-on articles which will show you how to
access the resources within your process model by scripting.

It is Friday afternoon and the boss is becoming very anxious about the current
process modeling project for Monkey Zoo (a very important client). He wants to
know how many diagrams are now in the Monkey Zoo process model, he wants to
know their names, descriptions, versions, the date last changed and by whom. He
also wants to know the number of BPMN objects contained in each diagram in
order to get an idea of the complexity of each diagram. He wants this list on his
desk by 8.30AM Monday in time for a meeting with the client
You could use a pen and paper and transcribe the the information from the 150 or
more diagrams in the project or you could write a script to do it.

These days, when the topic of process model interchange arises, the discussion usually swings
around to interoperability via XPDL, BPEL or some other file format based on an Xml encoding.
There is another more dynamic way of interacting with a process model. It requires that the process
modeler has a DOM (Document Object Model) and a scripting language which makes it possible to
reference a process model's objects directly without requiring Xml transcoded files. ActiveModeler
Avantage is such a modeler, as well as providing XPDL 2.0 file interchange, it also provides a
.NET DOM for BPMN and the various UI library functions within the modeler.
Scripting comes into its own when you need to create add-hoc reports and lists, add your own
dialogs/user interfaces and generally interact with or contribute to the process model dynamically.

Lua for process modeling

Lua is a modern scripting language that keeps turning up in the oddest range of places, from being
used as the logic engine in WOW (the phenomenally successful World of Warcraft), to being
embedded in network appliances, used in DNA sequencing applications and in NASA. Lua offers
distinct advantages over Javascript, Python, Perl and others when used as an embedded scripting
engine, importantly it has a small memory footprint and high execution speed and an elegant
simplicity. Lua is a natural for process modeling applications.

The Avantage Lua plugin packages the Lua.NET scripting engine based on LuaInterface. For a very
interesting (but somewhat technical) description of the implementation see LuaInterface: Scripting the .NET CLR with Lua from the Journal of Universal Computer Science.
The Avantage Lua plugin itself gives you full access to both the Avantage APIs and all of the .NET
framework classes from within your script. To make it easy, a high level wrapper is provided by the
plugin which simplifies getting at the process model and some of the Avantage UI libraries.
Avantage, a Lua script is executed in its own dedicated process thread, so it has minimal impact on
the performance of the main UI thread. This allows Lua scripts to perform lengthy time consuming
work leaving the user free to continue with other things. Scripts can work with Windows.Forms, UserControls and any other .NET objects.

Lua DOM for Avantage

Lua is pretty easy to learn so this article does not try to teach you the language, for that you should
read the online book Programming in Lua by Roberto Ierusalimschy. What you do need to know is that in order to use a .NET class from Lua you must import it first. This is like a using statement in C#.

MessageBox = luanet.System.Windows.Forms.MessageBox
Color = luanet.System.Drawing.Color
File = luanet.System.IO.File
Path = luanet.System.IO.Path
ArrayList = luanet.System.Collections.ArrayList
To create a object is easy once it has been imported
myColor = Color(Color.Yellow)
myPath = Path(“C:\temp”)

The final thing to keep in mind is that unlike VB.NET, C#, Javascript, Java et al, you reference a
method with the “:” operator not “.”.

Lua DOM (Document Object Model)

In order to save you from any possible confusion, I can tell you right now that the Wikipedia
definition of a DOM is not accurate. It assumes that DOMs are exclusively the province of web
browsers, HTML and XML. This is not so. To be accurate, a DOM is a set of programming APIs targetting a specific application document domain. Naturally, for a web browser the domain is HTML however for a process modeler the domain is a process model. The namespace domain of the Lua DOM is KT.AM.Lua.DOM

Main components

ProcessModel

The process model DOM consists of two stacks. The base process model stack (known as BPTree) is composed of BPObjects. BPObjects can be arranged in hierarchies (BPTrees) and they take care of saving themselves (persisting) to files and other important stuff like providing a transactioning mechanism so that actions can be undone. BPObjects are the raw DNA from which a full process modeling stack is built.

The BPMN 1.0 stack (BPMNTree) inherits from the BPObjects stack (BPTree). The KT.AM.Core.Resources.ProcessModel.BPMN namespace is a complete implementation of BPMN 1.0 as a programming API. There is very little that you can't do with a BPMN process model in this way.

Process modeling stacks

You can access the complete BPMN 1.0 process model API documentation [ here ] as a .chm
(Microsoft Compiled Help) file.

Menus

Scripts can contribute menu items to any Avantage popup context menu. Popup context menus
contain actions that are applicable to the type of object selected. For example, a Diagram object has
different context menus to a Lane object's context menus. The different menus appear because the objects are different. We refer to an object's menus as object contributions. A script could for example popup a “Project report...” menu item when the user right-clicks on a Project object. When the user selects that item then a script handler is executed to perform the action which is advertised by the menu contribution.

Tables

A script usually needs to output stuff in order to be useful. A TableEditor object is provided
which provides a grid/table style window rendering of the output from your script. This is useful for
lists, reports etc. For text and integer columns, there are some simplified access functions. This is sufficient for the vast majority of output. For richer content tables the underlying XPTable object itself must be directly accessed (in order to provide features like image cells, drop-down lists, checkbox cells and
more).

The Task

1. Create a new popup menu item which will appear when the user right-clicks on any Project
item in the Avantage workspace.
2. Assign a Lua script function delegate to handle the action when the user clicks on this menu.
3. Create a Grid/table style report in response to this click. For each diagram in the selected
project output the information that the boss wants to see.

Creating the menu action

We are going to create an ObjectPopup menu. This kind of menu is tied to a specific class of .NET
object, and whenever an object of that type is selected in the Avantage workspace then the menu
item is displayed.

ObjectPopup(string ClassPath, string name, string menuId, string description)

In our example we want the menu to appear only when project objects are selected. The fully
enumerated interface name of a Project object is KT.AM.Core.Resources.Workspace.IProject
so this is the first parameter string of the ObjectPopup() function. The second parameter is the text
of the menu that the user will see, the menuID is a unique identifier which identifies your action and
the description is a short description of the action suitable for display in tooltip text.

theMenu = ObjectPopup("KT.AM.Core.Resources.Workspace.IProject", "Project report",
"Project_report_id", "Report on all diagrams in this project")

This function returns a LuaContributor object. LuaContributors enclose an Action object through
which you can control the menu itself. We will set an icon image for the menu. This is done by the
SetIcon() function:

SetIcon(string ImageRegistry, string ImageName)

The imageregistry is the name of one of several image registries in Avantage, we will use the
“BPIcons” registry in this example (the BPIcons registry contains the standard images for the
objects which appear in the BPTree). The imagename is the name of the image within the registry.
We will choose the “Property” icon. (Read more about the ImageRegistries.)

theMenu.Action:SetIcon("BPIcons", "Property")

Next, we need to tell the menu the name of the script function that is to be executed when the user
clicks the menu. The OnRun() function is used for this purpose. Its parameter is the name of the
Lua function to be run.

handler = theMenu.Action:OnRun(ClickThisRun)

The menu handler function receives two parameters. The args object contains the arguments, one of
the properties of the args object is the selected object in the navigator that is the subject of the
menu's action. In the code snippet below, a function called DoReport() is called.

 
function ClickThisRun(sender,args)
  DoReport(data.selectedObject)
end
 

Extending the context menu

Creating the report

The script will display its output in a window we call a TableEditor which is a typical grid
composed of columns and rows. The image below shows what they look like (the yellow window).

TableEditor window

Create the TableEditor object
theReport = NewReport(string title, Color backgroundColor, Color gridlineColor)

The title parameter is the name of the report which is to be displayed on the tab. When you Save the
report, this name is used for the file name. You can also specify the background color of the window and the color of the grid lines.

In order to prevent the window from being needlessly updated while it is being filled, it is usual to
Freeze() it. When the filling process is complete you Unfreeze() it and the window is drawn.

Add columns to it

When you initially create a TableEditor it doesn't have any columns – you have to define them in
your script. For simple tables, the AddTextColumn() function can be used to do this.
Currently the TableEditor object only directly allows you to create TextColumns. If you
need to create columns other than TextColumns then you need to do a little bit more work.
You can create the full repertoire of column types (ButtonColumn, CheckBoxColumn,
ImageColumn,NumberColumn, ProgressBarColumn,ComboBoxColumn DateTimeColumn
and ColorColumn) by accessing the TableEditor.Table property. This provides you with a
reference to an instance of an XPTable object. You can download the API documentation
for XPTable from here XPTable - .NET ListView meets Java's JTable.

column = report:AddTextColumn(string column_title, int width, bool sorted)
Adding rows

A Row must be created for each line of detail in your report. To create a new row use the
TableEditor:AddRow() function. AddRow returns a XPTable.Models.Row object.

ewrow = report:AddRow()
Setting the contents of a row cell

To set the contents of a cell you call the TableEditor:SetCell() function

TableEditor:SetCell(XPTable.Models.Row theRow, int columnIndex, string theValue)
report:SetCellText(newrow, 2, theDiagram.Name)
report:SetCell(newrow, 5, theDiagram.ID)
report:SetCell(newrow, 7, theDiagram.Version)
report:SetCell(newrow, 8, theDiagram.Author)
report:SetCell(newrow, 4, theDiagram.ModificationDate:ToShortDateString ())
report:SetCell(newrow, 3, theDiagram.CreationDate:ToShortDateString ())
 

Notice that the last two SetCell() calls do some .NET date formatting. Because the
BPD_Diagram.ModificationDate and BPD_Diagram.ModificationDate properties are actually
.NET DateTime objects in the process model we can call their ToShortDateString() methods (by
using the “:” operator)

Saving a report to a file

Filled TableEditors automatically enable the File menu Save as... menu action. The table is saved
in CSV (Comma Separated Values) format which is widely supported.

Getting a list of files to process

Now that you have a rough idea of the mechanics of creating a menu and EditorTables it is time to
get to work. If you remember, the menu Run handler receives a reference to object the user selected
(clicked on). Because we are only contributing to project objects, the selected object will always be
a project file.

What's in a project file? Essentially a project file contains a list of the files which are registered in
that project. These are usually .model, .organization, .categories, .txt, etc. The files we are interested
in are .model files because these contain BPMN process diagrams. A project file also has a
ParentFolder property which provides the directory information for the project. A project's Files[]
array property contains a list of the File objects it manages. File objects represent files in the
filesystem, they have name, URI and other attribute information. So, all we have to do is get the selected project when the Run is called and then examine every File object in its Files[] array looking for files with the .model extension. For each .model file found we will open it and then access its BPMN process model to get the necessary information for the report.

 
function DumpProject(report, theProject)
  if (theProject ~= nil) then
    row = report:AddRow()
    report:SetCell(row, 0, theProject.Name)
    files = theProject.RootFolder.Files
    filecnt = files.Length
    for fileno = 0, filecnt-1, 1 do
      file = files[fileno]
      if (file ~= nil) then
        if (string.find(file.URI, ".model") ~= nil) then
          newrow = report:AddRow()
          report:SetCell(newrow, 1, Path:GetFileName(file.URI))
          report:SetCell(newrow, 4, File:GetLastWriteTimeUtc(file.URI):ToString())
          report:SetCell(newrow, 3, File:GetCreationTimeUtc(file.URI):ToString())
          tree = OpenModel(file)
          if (tree ~= nil) then
            AnalyseModel(tree, report)
            tree = nil
          end
        end
      end
    end
  end
end
 
Getting into a process model

Given a .model file we can open it by calling the OpenModel() function. This function returns a
BPMNTree object (you can read more about them in the .chm file you downloaded earlier).
A process model may contain multiple diagram objects, they are contained in the tree's
BPMNTree.BPMN_Diagrams collection (of type BPD_Diagram).
The script function here iterates the BPMN_Diagrams collection.

 
function AnalyseModel(tree, report)
  for i = 0, tree.BPMN_Diagrams.Count,1 do
    theDiagram = At(tree.BPMN_Diagrams, i)
    if theDiagram ~= nil then
      newrow = report:AddRow()
      report:SetCellText(newrow, 2, theDiagram)
      --- report:SetCellText(newrow, 2, theDiagram.Name)
      report:SetCell(newrow, 6, ChildItemsCount(theDiagram))
      report:SetCell(newrow, 5, theDiagram.ID)
      report:SetCell(newrow, 7, theDiagram.Version)
      report:SetCell(newrow, 8, theDiagram.Author)
      report:SetCell(newrow, 4, theDiagram.ModificationDate:ToShortDateString ())
      report:SetCell(newrow, 3, theDiagram.CreationDate:ToShortDateString ())
      report:SetCell(newrow, 9, theDiagram.Description)
    end
  end
end
 

If you remember from earlier, BPObjects are hierarchical. BPObjects have parents and children, and
their children can have children etc. In our example, the boss wants to know how many items are in
each diagram, so we have to write some code to do this. That is what the ChildItemsCount()
function does.

 
function ChildItemsCount(diagram)
  recursive = true
  list = ArrayList()
  CollectBPDChildren(list, diagram, recursive)
  return list.Count
end
 

This function is a Lua wrapper for calling one of the workhorse functions of the process model –
CollectBPDChildren().
CollectBPDChildren(ArrayList list, BPObject obj, bool recursive)
CollectBPDChildren returns a flattened list of children of an object. If the recursive parameter is set
true then the children of the children etc are included in the list. In our example here we set
recursive true because we want to know the count of all objects contained directly and indirectly by
the diagram object.

Wrapping it up

This article really only just touches the surface of what you can do with the Lua scripting language,
BPMN and Avantage. In the next article I will explain how to script custom properties and introduce more of the DOM to you.

Appendix Image registry names

The Action:SetIcon() function allows you to decorate a menu item with a pre-defined icon. Below
is a list of the registries and their image names.

“StandardIcons”

New|Open|Save|SaveAll|SaveAs|Cut|Copy|Paste|Delete|Properties|Undo|Redo|Preview|Print|Search|ReSearch|Help|ZoomIn|ZoomOut|Back|Forward|Favorites|AddToFavorites|
Stop|Refresh|Home|Edit|Tools|Tiles|Icons|List|Details|Pane|Culture|Languages|
History|Mail|Parent|FolderProperties|FullScreen|Camera|Calculator|LayoutContent|
BookOpen

“BPIcons”

Model|ModelSelected|BPFolder|BPFolderSelected|AsisMap|AsisMapSelected|ToBeMap|
ToBeMapSelected|AutomatedMap|AutomatedMapSelected|AsisActivity|
AsisActivitySelected|ToBeActivity|ToBeActivitySelected|AutomatedActivity|
AutomatedActivitySelected|Candidate|CandidateSelected|Group|GroupSelected|
AsisMapSeries|AsisMapSeriesSelected|Error|ErrorSelected|ToBeMapSeries|
ToBeMapSeriesSelected|ComplexModel|ComplexModelSelected|FormItem|
FormItemSelected|Rules|RulesSelected|Attachment|AttachmentSelected|Log|
LogSelected|Department|DepartmentSelected|Role|RoleSelected|Product|
ProductSelected|StartEvent|StartEventSelected|IntermediateEvent|
IntermeditateEventSelected|EndEvent|EndEventSelected|Task|TaskSelected|
MeasurePoint|MeasurePointSelected|Property|PropertySelected|Gateway|
GatewaySelected|Diagram|DiagramSelected|Pool|PoolSelected|Lane|LaneSelected|
TriggerNone|TriggerNoneSelected|TriggerMessage|TriggerMessageSelected|
TriggerTimer|TriggerTimerSelected|TriggerException|TriggerExceptionSelected|
TriggerCancel|TriggerCancelSelected|TriggerCompensation|
TriggerCompensationSelected|TriggerRule|TriggerRuleSelected|TriggerLink|
TriggerLinkSelected|TriggerMultiple|TriggerMultipleSelected|TriggerTerminate|
TriggerTerminateSelected|GatewayAND|GatewayANDSelected|GatewayOR|
GatewayORSelected|GatewayComplex|GatewayComplexSelected|GatewayXOREvent|
GatewayXOREventSelected|GatewayXOR|GatewayXORSelected|MetricatedPropertyActive|
MetricatedPropertyActiveSelected|MetricatedPropertyInactive|
MetricatedPropertyInactiveSelected|SequenceFlow|SequenceFlowSelected|
ConditionalFlow|ConditionalFlowSelected|MessageFlow|MessageFlowSelected|
Association|DirectionalAssociation|ExceptionFlow|CompensationAssociation|
PropertySet|PropertySetSelected|BPMNProcess|BPMNProcessSelected|BPMNSubProcess|
BPMNSubProcessSelected|DataObjectArtifact|DataObjectArtifactSelected|
AnnotationArtifact|AnnotationArtifactSelected|GroupArtifact|
GroupArtifactSelected

Complete listing of the script

 
MessageBox = luanet.System.Windows.Forms.MessageBox
Color = luanet.System.Drawing.Color
File = luanet.System.IO.File
Path = luanet.System.IO.Path
ArrayList = luanet.System.Collections.ArrayList
 
tablenumber = 0
 
function ChildItemsCount(diagram)
  recursive = true
  list = ArrayList()
  CollectBPDChildren(list, diagram, recursive)
  return list.Count
end
 
function AnalyseModel(tree, report)
  for i = 0, tree.BPMN_Diagrams.Count,1 do
    theDiagram = At(tree.BPMN_Diagrams, i)
    if theDiagram ~= nil then
      newrow = report:AddRow()
      report:SetCellText(newrow, 2, theDiagram)
      --- report:SetCellText(newrow, 2, theDiagram.Name)
      report:SetCell(newrow, 6, ChildItemsCount(theDiagram))
      report:SetCell(newrow, 5, theDiagram.ID)
      report:SetCell(newrow, 7, theDiagram.Version)
      report:SetCell(newrow, 8, theDiagram.Author)
      report:SetCell(newrow, 4, theDiagram.ModificationDate:ToShortDateString ())
      report:SetCell(newrow, 3, theDiagram.CreationDate:ToShortDateString ())
      report:SetCell(newrow, 9, theDiagram.Description)
    end
  end
end
 
function DumpProject(report, theProject)
  if (theProject ~= nil) then
    row = report:AddRow()
    report:SetCell(row, 0, theProject.Name)
    files = theProject.RootFolder.Files
    filecnt = files.Length
    for fileno = 0, filecnt-1, 1 do
      file = files[fileno]
      if (file ~= nil) then
        if (string.find(file.URI, ".model") ~= nil) then
          newrow = report:AddRow()
          report:SetCell(newrow, 1, Path:GetFileName(file.URI))
          report:SetCell(newrow, 4, File:GetLastWriteTimeUtc(file.URI):ToString())
          report:SetCell(newrow, 3, File:GetCreationTimeUtc(file.URI):ToString())
          tree = OpenModel(file)
          if (tree ~= nil) then
            AnalyseModel(tree, report)
            tree = nil
          end
        end
      end
    end
  end
end
 
--- This func creates table editor window.
function DoReport(selectedProject)
  tablenumber = tablenumber + 1
  theReport = NewReport("Project Report"..tablenumber, Color.LemonChiffon, Color.Gray);
  theReport:Freeze()
  notsorted = false
  sorted = true
 
  projcol = theReport:AddTextColumn("Project", 120, notsorted)
  modelcol = theReport:AddTextColumn("Model", 120, notsorted)
  diagramcol = theReport:AddTextColumn("Diagram", 160, notsorted)
  createcol = theReport:AddTextColumn("Created", 80, notsorted)
  modcol = theReport:AddTextColumn("Modified", 80, notsorted)
  idcol = theReport:AddTextColumn("ID", 50, notsorted)
  activitycountcol = theReport:AddTextColumn("# Items", 60, notsorted)
  versioncol = theReport:AddTextColumn("Version", 80, notsorted)
  authorcol = theReport:AddTextColumn("Author", 60, notsorted)
  descrcol = theReport:AddTextColumn("Description", 150, notsorted)
 
  DumpProject(theReport, selectedProject)
  theReport:Unfreeze()
end
 
function ReportMenuClicked(sender, args)
  if (args ~= nil) then
    DoReport(args.selectedObject)
  end
end
 
function UnloadContributions(sender, args)
  MessageBox:Show("The project reporting thread is now terminated")
  Terminate()
end
 
--- Create an object popup menu
os.setlocale("en_US.UTF-8")
clickThis = ObjectPopup("KT.AM.Core.Resources.Workspace.IProject", "Project report", "Clickthis_1", "Report on all diagrams in project")
clickThis.Action:SetIcon("BPIcons", "Property");
handler = clickThis.Action:OnRun(ReportMenuClicked);
 
unload = ObjectPopup("KT.AM.Core.Resources.Workspace.IProject", "Unload project reporting", "report_unload", "Remove reporting menus")
unload.Action:OnRun(UnloadContributions)
 
--- This script thread will now sleep forever if there are contributions defined. To force unloading when you have contributions
--  you must call Terminate().
 

BPMN is not just for process automation experts

There is a perception that BPMN is complex and technical. That is not true, it is just that there is so much interest and use of BPMN in the process automation sector (workflow, B2B, webservice definitions and the like) that its virtues for business analysis flowcharting have been over looked in the rush. This article explains why you should use BPMN instead of a non-standard 'electric pencil' type product when making even the simplest of flow charts.

The next time you need to produce a flowchart resist the urge to fire up Visio and consider using a native BPMN modeler instead. BPMN is now the standard for drawing flows, see bpmn.org

The flow chart has been essential computer fare since the very early days. Today an entire genre of software products caters to the flow charting market. People and companies use flow charting software to describe procedures for quality control, corporate transparency, training and education, and many other uses.

BPMN is not hard to use

Did you know that BPMN was designed so that you can use just a little or a lot - or somewhere in between? If you only need to make a simple flow chart then you don't have to know anything about MIOrdering, LoopTypes, IORules, Participants, Webservices and their ilk, you don't even have to use Swimlanes or Pools. BPMN was expressly designed this way in recognition of the historical usage of flow charting in the general business community.
Minimal BPMN diagram

The problem is that most of the cu