Introduction to FLEXSCHE Products

FLEXSCHE Version 19

FLEXSCHE version 19.0 was released on December 27, 2019. It includes 174 feature enhancements. Here are some of the main ones. (Differences between version 18.0 and version 19.0)

FLEXSCHE WebViewer

It is now possible to view a simple Gantt chart in a web browser without incurring any costs.

FLEXSCHE WebViewer Screen

As a method to present the results planned by the production scheduler to the manufacturing site, it is often a local "work instruction" for individual workers or each piece of equipment. However, there may also be cases where you want to get an overview using a Gantt chart or similar. Additionally, it is also required that managers (such as headquarters or factory managers) and the sales department can grasp the factory's situation at any time.

Traditionally, for such needs,FLEXSCHE Viewerwe have been providing solutions. This offers the same high-level screen display functions as FLEXSCHE GP used by planners, enabling visualization of plans from various perspectives. However, the drawback was that a license needed to be prepared for each client, which increased costs as the number of clients grew.

Therefore, with the release of version 19,FLEXSCHE WebViewerwe have decided to start offering (abbreviated as FWV). FLEXSCHE WebViewer is a simple Gantt chart viewer that operates on a web browser. While the information that can be displayed and the functions are limited, it is a product that meets the demand for "just wanting to get an overview easily."

FLEXSCHE WebViewer can be used free of charge, but only data output from a license with a valid maintenance contractFLEXSCHE GPorFLEXSCHE CarryOutcan be displayed.

System Configuration of FLEXSCHE WebViewer

Output of WebViewer Data

On FLEXSCHE GP with a valid maintenance contract, set the output method to FLEXSCHE WebViewer and perform the data output process. If you place the created configuration file on the FLEXSCHE CarryOut server, you can also output data from FLEXSCHE CarryOut.

The strings, colors, and chart row configurations displayed in the Gantt chart can be defined using the familiar expressions in FLEXSCHE. You can also hierarchically structure the chart rows in a tree format.

FLEXSCHE WebViewer Server

You can place the output data on a general web server to view it with FLEXSCHE WebViewer, but by operatingFLEXSCHE WebViewer Serverwithin the intranet, you can push updates to the browser each time the data is updated.

Note that the operating environment for the WebViewer server does not depend on the OS type as long as Node.js is operational.

FLEXSCHE WebViewerSample Screencan be viewed. However, since the FLEXSCHE WebViewer server is not operational, you cannot check the push distribution function for updated data here.

For instructions on how to operate the chart, click on the?at the top right of the chart screen.

The supported browsers are Google Chrome / Mozilla Firefox. Microsoft Edge is not supported at this time, and some features, such as drawing work connection lines, are not available.

Software-based licensing

It is now possible to choose a license without a hardware key (dongle),
making license management in data centers easier.

We have released a software-based license system that does not use hardware,Software-based licensingwhich does not require a USB license key, allowing licenses to be installed on server machines or virtual machines without USB ports. Additionally, unlike hardware keys, the risk of loss is significantly reduced.

Even if the machine on which the license is installed fails and cannot be started,as part of the maintenance service,the license can be reissued.

FLEXSCHE Performance Tuning Service

As a new service for users with maintenance contracts,
FLEXSCHE Performance Tuning Service (FPTS)we will start.

FLEXSCHE is optimized to the extreme for the shortest scheduling processing time, but even so, with large-scale data or complex scheduling logic, considerable processing time may be required. We have received requests to shorten this time as much as possible, and in response, we have launched a new service.

In this service, customers themselves operate FLEXSCHE to collect profiles, and based on that, we create and provide a FLEXSCHE installer dedicated to the customer. By focusing on the customer's unique data and optimizing each program module of FLEXSCHE, it is expected that the processing speed of FLEXSCHE will be further accelerated for that data, logic, and operation procedure.

Details of this service

Flow of Module Provision

  1. Profile Collection

    Please prepare the data in operation or equivalent data. Perform the same operations as during operation to create the characteristic and trend information (profile) of the process. A module for profile collection is included, so it needs to be replaced in advance.

    * The profile collection module takes time to execute. Expect about 10 times the usual time required.

  2. Profile Submission

    Please send the collected profile information to FLEXSCHE Corporation.

  3. Build Dedicated Module (FLEXSCHE Corporation)

    Based on the submitted profile, we will build a user-specific module within our company.

    * It will take a few days.

  4. Acquisition of Dedicated Module

    We will notify you by email when the build is complete. You can download the dedicated module that has been accelerated.

  5. Application of Dedicated Module

    By replacing the downloaded dedicated module with the existing module of FLEXSCHE, the acceleration application is complete.

Flow of Module Provision

FPTSManager and FPTS Server

To carry out the above procedures, a tool called FPTSManager is used. Operations such as profile creation and submission, acquisition of the built dedicated module, and module replacement are performed with this tool. Also, a web service called FPTS Server is running on our side, and FPTSManager interacts with this server, so there is no need to contact our staff directly. There is also no need to directly manipulate files using Explorer, etc.

In maintenance mode, you can replace the acquired dedicated module with the standard module and start FLEXSCHE. It is convenient for reverting to the state before acceleration application and for comparative verification of the acceleration effect by FPTS. You can also delete old files from here.

FPTSManager

Other Supplementary Information about the Service

  • It only applies to the latest release version/revision of the maintenance target version.
  • We cannot guarantee specific figures for how much acceleration can be expected.
  • Since FLEXSCHE is already optimized to the extreme, there may be cases where no effect is seen depending on the data and processing content. Sometimes it may even become slower.
  • The profile information is merely aggregated information about the program's operational tendencies. It does not include project-specific information, so please rest assured.
  • Even if the PC with FLEXSCHE installed is in an offline environment, you can copy FPTSManager to another PC with an online connection to perform only the procedural part with the FPTS server.
  • If you wish to have an acceleration module for a corrective release, you will need to redo the procedure from profile collection.

This service is only provided for licenses with a maintenance contract.

Debug trace function

It is a mechanism to observe the state during scheduling.

As you proceed with building scheduling rules, there are often cases where it is difficult to pinpoint the cause when the scheduling results differ from expectations. In such situations, you may want to pause (break) during the scheduling process to carefully observe the state.

Breakpoint Setting

The "Debug Trace Function" implemented in version 19 makes it possible.

"Breakpoints" are set at various points in the scheduling process, and enabling them allows you to break. By providing a "break condition" as an expression to the breakpoint, you can also break only when specific conditions are met. You can freely define expressions for displaying the internal state at each breakpoint.

Debug Panel

Debug Panel

The "Debug Panel," which consolidates the debug trace function, offers various trace operations. By utilizing "Step-by-Step Execution," which executes the scheduling process one step at a time, "Continue," which proceeds until the next break condition is met, and "Target Object Search," which shows the last processed object (such as operations) on the Gantt chart, you can quickly identify the problematic areas.

While breaking, you can operate normally, such as switching screens, scrolling, zooming, and operating dialogs, except for some commands. You can even move operations with the mouse, which carries the risk of creating unexpected inconsistencies depending on the rules, but it should be a very powerful aid in constructing scheduling rules.

Note that this function is only enabled when the user role is set to "Advanced User" or higher, and it is disabled when set to "General User."

High DPI support

FLEXSCHE now operates comfortably in high DPI environments.

FLEXSCHE now operates comfortably in high DPI environments, where the display is high resolution but not large in size, such as on laptops or tablet PCs. In high DPI environments, the system's font size is usually enlarged. Applications need to accommodate this, but simply enlarging the application can result in blurred or jagged text and rough UI rendering.

In this update, FLEXSCHE uses font sizes corresponding to the system's font size and enlarges UI components as needed, achieving a smoother appearance compared to the traditional enlargement mode.

Traditional Enlargement Mode
Simply scaled to double size
Text becomes blurred or jagged
Chart appearance is rough

High DPI Support Mode
Font size adjusted to magnification, UI components enlarged as needed
Text is clear
Chart appearance is smooth

EDIF

We have enhanced the following features related to EDIF and the EDIF Configuration Tool.

Export of Squad Resource Subtasks

It is now possible to export the details of tasks assigned to squad resources, specifically the subtasks (assignment status to squad members). It supports field separation and table separation, and in the case of table separation, expressions can also be used.

Transaction Support for Keyed Custom Sets

Integration with t_tran and t_last_updated fields is now supported. Transaction processing similar to regular FLEXSCHE tables can be performed.

Support for Differences in Results, Inventory Operations, and Free Calendars

Records can now retain codes, allowing for differential import/export.

Specification of Command Timeout for ADO and ADO.NET

Command Timeout Specification

The timeout field for CSV files in the external table settings is now also effective for ADO/ADO.NET, functioning as a timeout setting for DB commands.

Direct Specification of SQL During Import

It is now possible to execute arbitrary SQL queries and freely filter the records obtained from the DB. When importing a portion of large data into FLEXSCHE, dramatic speed improvements can be expected compared to before.

 Select * from tableA where xxx='val1'

By specifying SQL statements like this, filtering can be done before FLEXSCHE receives the data. Previously, all records had to be scrutinized and selected on the FLEXSCHE side, incurring costs for retrieval from the DB. The more data there is, the greater the benefit.

It is important to note that there is a high degree of freedom, allowing for the writing of update or delete statements, among others.

Make Error Locations Clearer

Make Error Locations Clearer

Error marks are now displayed on the tabs of table mappings that contain errors. Previously, a warning message was displayed when errors were present at the time of saving, but it was sometimes difficult to find which table mapping contained the error. In addition to displaying error marks on the tabs, you can now filter by "Table Mappings Containing Errors" using the group filter, significantly improving the efficiency of correction work.

Operation Result Subdivision

An operation result subdivision table has been added to specify supplementary information related to operation results, allowing you to specify result information for subtasks of squad resource members.

For example, in large-scale assembly operations where multiple workers take turns working at their own timing, you can accurately reproduce on the resource Gantt chart which time slots each worker was responsible for as a result.

Operation Result Subdivision
* The advanced option "Squad Resource" (2 units) is required to reflect assignments to squad resource members.

Scheduling

[Data Validation] Mark Violating Records

In the Validate Data Method, you can now set a mark (free flag) on records that violate each validation item. For example, by linking with the filter function of the FLEXSCHE Editor, you can easily extract data where abnormalities have been found.

[Replenishment Production] Specify Upper Limit & Leveling in Period Batch Replenishment

In period batch replenishment, you can now specify the upper limit of the order quantity for the generated replenishment orders. If a quantity exceeding that is required, it will be generated by dividing it into multiple replenishment orders. You can also level the quantities of the generated replenishment orders at that time.

Upper Limit Specification & Leveling in Period Batch Replenishment

[Replenishment Production] Define Replenishment Batch Period with Expressions

You can now freely define the cutoff time of the replenishment batch period with expressions. For example, in cases where "the required quantity is replenished monthly," the length of the batch period varies by month. Previously, the length of the replenishment batch period could only be set as a fixed value for each item, but now it can be achieved simply by specifying an expression that returns the first date of each month in a list.

[Modeling] Selector by Expression

You can now specify the selector conditions for the selected side with expressions. For example, it is easy to automatically switch production processes according to the due date of production orders.

Moreover, in the past, it was not possible to mix AND and OR conditions in the matching judgment with the conventional order selector, but now it can be completely freely described with expressions.

[Modeling] Support for Simul-loading and Parallel Conditions Only for Changeover

Even task resources involved only in changeover can now comply with simul-loading and parallel conditions. By efficiently finding the times when conditions can be met in each part of setup, manufacturing, and teardown, you can create an efficient plan.

[Workshop Planning] Improved Accuracy of Margin Processing

Improvements have been made to accurately perform placement planning considering margins even when the workpiece shape is a concave polygon.

Improvement in Margin Processing Accuracy

User Interface

[Timeline Chart] Aggregated Display by Arbitrary Timeranges

In inventory level charts, load charts, resource idle charts, item idle charts, and signboards (expressions), you can now freely specify the cutoff times within a day for each chart row, allowing for aggregated display between them.

Improvement in Margin Processing Accuracy

[Operation Connection Line] Shape of Operation Connection Line

In the Resource Gantt Chart and Order Gantt Chart, you can now choose not only straight lines but also hook-shaped lines as the shape of the connection lines between operations.

Shape of Operation Connection Line (Traditional)
Shape of Operation Connection Line (New)

[Operation Sequence Chart] Display Timerange Limitation

In the Operation Sequence Chart, you can now limit the display timerange for each chart. For example, in the case of shift work, you can display only the time range of the shift you are responsible for.

[Operation Sequence Chart] Page Breaks at Period Boundaries

When displaying the Operation Sequence Chart segmented by period, you can now specify that page breaks should not occur except at period boundaries when printing.

[Operation Sequence Chart] Open in Excel

You can now open the display content of the Operation Sequence Chart directly in Excel. The background color of cells and text color are also reproduced.

[Window] Color on Window Tabs

You can now set colors on the tabs of each window. Colors corresponding to the type, such as Timeline Chart or FLEXSCHE Editor tables, are set. Additionally, you can specify individual colors for each window. This allows you to grasp various windows at a glance.

Color on Window Tabs

[Skill Editor] Edit More Than Just Skills

In the Skill Editor, you can now edit not only the skills of resources but also the numerical specifications of resources, items, and orders. This is convenient when you need to input a large amount of data for multiple numerical specification keys in a tabular format.

Expression

Functions to Modify Lists and Maps

We have added functions to modify only some values in lists and maps.
The description of expressions has become more concise, and performance has improved.

Previously, lists and maps in FLEXSCHE had a property called immutability, which meant that once created, you could not modify part of the values. In other words, to change a list (or map), you had to operate on a copy of the original and return a new list/map.

For example, consider a list {'a', 'b', 'c', 'd'} that a variable $list refers to.

List

The expression to add 'X' to the end of this list used to be as follows. The original list remains unchanged, and the operation on the duplicated list becomes the result.

$list := $list.Append('X')
Immutable Operations

When dealing with large lists/maps, the processing cost of such duplication operations is not low. In version 19, you can directly modify the original list without duplicating it by writing as follows.

$list.Append_('X')
Mutable Operations

In addition to .Append_() to add values to the end, .Set_() to modify some values, and .Remove_() to remove elements have been added.

This mechanism is particularly effective in improving performance when cumulatively adding elements to lists or maps referenced by stored variables.

Expression Editing Support Function

You can now easily test expressions by selecting the evaluation target from the project panel. Additionally, comments written in expressions are displayed in green, making the expressions easier to read than before.

{'a', 'b', 'c'}

Expansion of Stored Variables

As a mechanism to control the timing of expression evaluation and improve performance,Stored Variablesnew stored variables have been added. Similar to project properties, but with more data types that can be handled, can be directly used as variables, and can have descriptions written, making them convenient in various ways.

You can now specify whether to write the value of stored variables to a file. This avoids unnecessary overhead from reading and writing large lists or maps to files that are only temporarily used during scheduling.

Parameter

You can now specify records of custom datasets as parameters. You can directly pass records without declaring a record-type parameter and converting it like Custom('dataset').From($rec).

Integration with External Programs

We have added the function Project.ConsoleCommand, which allows you to execute any program and incorporate its standard output into expressions. For example, you can perform calculations in a language like Python, which has a rich library for numerical calculations, and reflect the results in FLEXSCHE.

また、外部のProgramに構造的な値to受け渡すandきにJSON形式でデータto表現したいIandisあります。 新しくAddされた関数、<Map>.ToJSON / <List>.ToJSON / <Variant>.TOJSON / Variant.FromJSONにより、taktデータandJSONto相互変換できるようになりました。

Usage Example

By combining these, for example, in an external pytest.py file,

import sys
import json
import numpy as np
data = json.loads( sys.argv[1] )
angle = np.deg2rad( data["angle"] )
vec = np.array(data['value'])
cos = np.cos( angle )
sin = np.sin( angle )
matrix = np.array([[cos,-sin],[sin,cos]])
vec = np.dot( matrix, vec.transpose() )
print( json.dumps( vec.tolist() ) )	

you can describe and evaluate it in FLEXSCHE,

$vec := {22, -4},
$data := { "value"=>$vec, "angle"=>45 },
$a1 := "pytest\pconv.py",
$a2 := $data.ToJSON,
$res := Project.ConsoleCommand( "python", { $a1, $a2 } ),
Variant.FromJSON( $res )	

allowing you to perform vector calculations in an external program and incorporate the results into FLEXSCHE.

Various functions added

The number of functions available in expressions has increased, further expanding what you can do.

Functions Added in Version 19

Basic types
Time Class Time.FromYMDHMS
Variant Class Variant.FromJSON
<Variant>.ToJSON
Container Type
Map Class <Map>.Set_
<Map>.Remove_
<Map>.Update_
<Map>.ToJSON
<Map>.ForEach
List Class <List>.IsMutable
<List>.Duplicate
<List>.Set_
<List>.Remove_
<List>.Append_
<List>.Insert_
<List>.ToJSON
Object types
CTT class <CTT>.PrecedingStrings
<CTT>.PrecedingRange
<CTT>.FollowingStrings
<CTT>.FollowingRange
Record Class <Record>.MakeList
Inventory Class <Inventory>.Destination
Item Class <Item>.Subdivision
Operation class <Operation>LookupCTT
Order class <Order>.EffectiveItemRec
Proc class <Proc>.SubstituteCandidates
Resource class <Resource>.Skills
<Resource>.AssignedTasks
ResultSubdivision Class <ResultSubdivision>.OperationCode
<ResultSubdivision>.TaskPart
<ResultSubdivision>.TaskKey
<ResultSubdivision>.Resource
<ResultSubdivision>.ResourceQty
<ResultSubdivision>.StartTime
<ResultSubdivision>.EndTime
Shape class <Shape>.CountOfAreaConstraints
<Shape>.AreaConstraint
AfterTest class <AfterTest>.CheckResourceOccupation
<AfterTest>.WorkingVolumeInPeriod
Other
Selectors Class <Selectors>.IsEmpty
<Selectors>.Has
<Selectors>.HasOrEmpty
<Selectors>.H
<Selectors>.NH
<Selectors>.E
<Selectors>.NE
<Selectors>.HE
<Selectors>.NHE
<Selectors>.Order
DataCube Class <DataCube>.ReadOnly
Math class Math.GCD

Other

Data Cube Editor as a UI Component

You can now easily develop GUI embedded screens with a table format UI.

Data Cube Editor as a UI Component

You can now create a data cube viewer where cell values can be edited. You can freely control the enable/disable status, background color, and editability of each cell or row/column from add-ins.

For example, you can create a UI where the horizontal axis is the date, and the vertical axis is the item, allowing you to input the demand quantity for each item on each day. For instance, when a value is entered, you can use an add-in to create an order with that day as the due date and assign operations accordingly.

*A FLEXSCHE Analyzer license is required.

Code Example

The following add-in script implements a UI for humans to adjust the production quantity of intermediate materials according to the demand quantity of finished products.

// IのFLEXSCHEAdd-inのコードは自由に改変してお使いいただくIandisできます

// GUIAdd-inの登録
function SelfRegistration(addIns) {
  var addin;
  addin = addIns.AddScript("Setup", FLEXSCHE.AddInKeyHookAfterLoadingProject);
  addin = addIns.AddScript("Command", FLEXSCHE.AddInKeyEventFSEventFired);
  addin.LongValue = addIns.Application.Environment.RegisterProjectEvent(
    "gui.tree-node.command.invoked" );
  // プロジェクト読み込み時のDataCubeView用Data Cubeto作る
  addin = addIns.AddScript(
    "ObtainDatacube", FLEXSCHE.AddInKeyEventFSEventFired );
  addin.LongValue = addIns.Application.Environment.RegisterProjectEvent(
    "fse.datacube.obtain" );
  // 全体to更新
  addin = addIns.AddScript(
    "AfterLoadingData", FLEXSCHE.AddInKeyHookAfterLoadingData );
  addin = addIns.AddScript("Rescheduled", FLEXSCHE.AddInKeyEventFSEventFired);
  addin.LongValue = FLEXSCHE.FSEventRescheduled;
}

// EditorAdd-inの登録
function SelfRegistrationForFSEditor(addIns) {
  var addin = addIns.AddScript(
    "ValueChanged", FSEditor.FSEAddInKeyEventOnBodyOnDataCubeEditor );
  // セルis編集された => 当該Nakata間品andその下位Productだけto更新
  addin.SubKeyID = FSEditor.FSEAddInSubKeyEvent_Edited;
}

function _Setup(keyEntity) {
  // プロジェクトパネルの「カスタムビュー」ノード
  var project = keyEntity.ParamObject(FLEXSCHE.ParamIDProject);
  var str = "<?xml version='1.0'?>";
  str += "<tree-node str='カスタムビュー' "
  str += "guid='{41D5879D-EF89-48C1-A681-39D57EEC5423}' type-name='top'>";
  str += "<command str='Add' id='add-view' is-default='true' />";
  str += "</tree-node>";
  var cmd = new ActiveXObject("Microsoft.XMLDOM");
  cmd.loadXML(str);
  project.BehaviorProperty(
    "#gui.project-panel.additional-tree.custom-dc" ) = cmd.documentElement;
  // 既存の子ノードAdded
  var items = project.ObtainStoredData("jsobject.DCView.Items.1", []);
  for( var i = 0; i < items.length; i++ ) AddView(project, items[i].guid, false);
  return true;
}

// ツリー項目のコマンドto実行
function _Command(keyEntity) {
  var project = keyEntity.ParamObject(FLEXSCHE.ParamIDProject);
  var nodeType = keyEntity.ParamString(FLEXSCHE.ParamIDVariant1);
  var guid = keyEntity.ParamString(FLEXSCHE.ParamIDVariant2);
  var command = keyEntity.ParamString(FLEXSCHE.ParamIDVariant3);
  if( nodeType == "top" && command == "add-view" ) {
    // Add
    var sdlUtil = project.Application.CreateCOMInstance("SDLib.SDLUtility");
    var newGuid = sdlUtil.GenerateGUID(true);
    AddView(project, newGuid, true);
    var items = project.ObtainStoredData("jsobject.DCView.Items.1", []);
    items.push({ guid: newGuid });
    project.StoredData("jsobject.DCView.Items.1") = items;
  }
  if( nodeType == "view" && command == "show-view" ) {
    // 表示
    var dc = GetDatacube(project, guid);
    var fseProject = GetFSEditorProject(project);
    if( fseProject != null ) {
      var dcEditor = fseProject.ViewDataCube(dc, true);
    }
  }
}

// プロジェクト読み込み時のDataCubeView用Data Cubeto作る
function _ObtainDatacube(keyEntity) {
  var project = keyEntity.ParamObject(FLEXSCHE.ParamIDProject);
  var guid = keyEntity.ParamString(FLEXSCHE.ParamIDVariant2);
  var items = project.ObtainStoredData("jsobject.DCView.Items.1", []);
  for( var i = 0; i < items.length; i++ ) {
    if( items[i].guid != guid ) continue;
    var dc = GetDatacube(project, guid);
    if( dc == null ) break;
    keyEntity.Param(FLEXSCHE.ParamIDVariant3) = dc;
    return true;
  }
  return false;
}

function GetDatacube(project, guid) {
  var cDCs = project.CountOfStockedObjects("datacube");
  for( var iDC = 0; iDC < cDCs; iDC++ ) {
    var dc = project.StockedObject("datacube", iDC);
    if( dc != null && dc.guid == guid ) return dc; // 既存のData Cubeto返す
  }
  var sdSpace = project.DataSpace;
  var dc = project.Application.CreateCOMInstance("SDLib.DataCube");
  dc.GUID = guid;
  dc.Name = "PSI-01";
  project.AddStockedObject("datacube", dc);
  // Date and Timeディメンジョン
  var dimTime = dc.AddDimension("Time", SDLib.DCVTypeTime, "");
  dimTime.DisplayName = "Date";
  var startDate = VBDateToJDate(project.HorizonStartDate);
  var endDate = VBDateToJDate(project.HorizonEndDate);
  var exp = sdSpace.CreateTypedExpression(
    SData.SDVTypeTime, SData.SDVTypeString );
  exp.Parse(".ToString('%^m/%^d')");
  for( var date = startDate; date <= endDate; date.setDate(date.getDate() + 1) ) {
    var _d = VBDateFromJDate(date);
    var elem = dimTime.PrimitiveLayer.AddElement(_d);
    elem.Description = exp.CalculateFor(_d);
  }
  // 品目ディメンジョン
  var dimItem = dc.AddDimension("Item", SDLib.DCVTypeCustomString, "Item");
  dimItem.DisplayName = "品目";
  var layerItemIntermediate = dimItem.AddLayer("intermediate");
  dimItem.RootLayer.AddChild(layerItemIntermediate);
  layerItemIntermediate.AddChild(dimItem.PrimitiveLayer);
  var intItems = sdSpace.Calculate("Item.Records.Select([.IsIntermediate])");
  var cIntItems = intItems.Count;
  for( var iIntItem = 0; iIntItem < cIntItems; iIntItem++ ) {
    var intItemRec = intItems.ItemRec(iIntItem);
    var layerElem = layerItemIntermediate.AddElement(intItemRec.Code);
    var prodItems = sdSpace.Calculate(
      "Item.Records.Select([.IsFinal and .Comment('mtrl')='" + intItemRec.Code + "'])"
    );
    var cProdItems = prodItems.Count;
    for( var iProdItem = 0; iProdItem < cProdItems; iProdItem++ ) {
      var prodItemRec = prodItems.ItemRec(iProdItem);
      layerElem.AddChild(dimItem.PrimitiveLayer.AddElement(prodItemRec.Code));
    }
  }
  // メジャーの定義
  var mdefLimit = dc.AddMeasureElementDefinition(SDLib.DCMEDTypeNone, "Limit");
  mdefLimit.ValueType = SDLib.DCVTypeDouble;
  mdefLimit.DisplayName = "要求上限";
  var mdefRequired = dc.AddMeasureElementDefinition(
    SDLib.DCMEDTypeNone, "Required" );
  mdefRequired.ValueType = SDLib.DCVTypeDouble;
  mdefRequired.DisplayName = "要求量";
  var mdefProduce = dc.AddMeasureElementDefinition(
    SDLib.DCMEDTypeNone, "Produce" );
  mdefProduce.ValueType = SDLib.DCVTypeDouble;
  mdefProduce.DisplayName = "生産量";
  var mdefStock = dc.AddMeasureElementDefinition(SDLib.DCMEDTypeNone, "Stock");
  mdefStock.ValueType = SDLib.DCVTypeDouble;
  mdefStock.DisplayName = "残量";
  var mdefVirtual = dc.AddMeasureElementDefinition(
    SDLib.DCMEDTypeNone, "Virtual" );
  mdefVirtual.ValueType = SDLib.DCVTypeDouble;
  mdefVirtual.DisplayName = "仮想生産量";
  dc.FinishToSetup();
  // 表示・読み取り専用の制御
  var iStock = dc.MeasureElementIndexByName("Stock");
  var iProduce = dc.MeasureElementIndexByName("Produce");
  var iLimit = dc.MeasureElementIndexByName("Limit");
  var iVirtual = dc.MeasureElementIndexByName("Virtual");
  layerItemIntermediate.MeasureElementHidden(iLimit) = true;
  dimItem.PrimitiveLayer.MeasureElementHidden(iStock) = true;
  layerItemIntermediate.MeasureElementHidden(iVirtual) = true;
  dimItem.PrimitiveLayer.MeasureElementHidden(iVirtual) = true;
  dc.ReadOnly = false;
  layerItemIntermediate.MeasureElementReadOnly(iStock) = true;
  layerItemIntermediate.MeasureElementReadOnly(iProduce) = true;
  dimItem.PrimitiveLayer.MeasureElementReadOnly(iLimit) = true;
  dimItem.PrimitiveLayer.MeasureElementReadOnly(iProduce) = true;
  // 過去期間to読み取り専用に
  var roDays = sdSpace.Calculate(
    "TimeList.MakeInRange(project.HorizonStart,Project.SchedulingStartTime)" );
  var cROs = roDays.Count;
  for( var iRO = 0; iRO < cROs; iRO++ )
    dimTime.PrimitiveLayer.ElementByValue( roDays.Value(iRO) )
      .MeasureElementReadOnly(-1) = true;
  UpdateValues(dc, project);
  return dc;
}

// ビューのツリー項目Addedする
function AddView(project, guid, diff) {
  var topElem = project.BehaviorProperty(
    "#gui.project-panel.additional-tree.custom-dc" );
  var doc = topElem.ownerDocument;
  if (diff) topElem.setAttribute("sync", "true");
  // <tree-node str='PSI-01' guid='4E16AE33E53440069A71A5083275BA95'
  //   type-name='view' icon='datacube' />
  var viewElem = doc.createElement("tree-node");
  topElem.appendChild(viewElem);
  viewElem.setAttribute("str", "PSI001");
  viewElem.setAttribute("guid", guid);
  viewElem.setAttribute("type-name", "view");
  viewElem.setAttribute("icon", "datacube");
  // <command str='表示' id='show-view' is-default='true' /'>
  var commandElem = doc.createElement("command");
  viewElem.appendChild(commandElem);
  commandElem.setAttribute("str", "表示");
  commandElem.setAttribute("id", "show-view");
  commandElem.setAttribute("is-default", "true");
  project.BehaviorProperty(
    "#gui.project-panel.additional-tree.custom-dc" ) = topElem;
}

function GetFSEditorProject(project) {
  var fse = project.Environment.AddInManager.InterfaceByProgID(
    "FSEditor.Entries" );
  if( fse == null ) return null;
  var fseEnv = fse.Accessor.Environment;
  if( fseEnv == null ) return null;
  return fseEnv.Project;
}

/***************************************************************************************/

// セルの値is変わった
function _ValueChanged(keyEntity) {
  var editor = keyEntity.ParamObject(FSEditor.FSEParamIDDataCubeEditor);
  var row = keyEntity.ParamLong(FSEditor.FSEParamIDRow);
  var col = keyEntity.ParamLong(FSEditor.FSEParamIDCol);
  var locator = keyEntity.ParamObject(FSEditor.FSEParamIDDataCubeLocator);
  var meIndex = keyEntity.ParamLong(FSEditor.FSEParamIDLong);
  var measure = locator.FindMeasure();
  if (measure == null) return false;
  var util = Script.CreateCOMInstance("SDLib.SDLUtility");
  var project = editor.Project.FSProject;
  var sdSpace = project.DataSpace;
  var dc = locator.DataCube;
  var iTime = dc.DimensionByName("Time").IndexInDataCube;
  var iItem = dc.DimensionByName("Item").IndexInDataCube;
  var time = locator.DimensionLayerElement(iTime).Value;
  var itemRec = sdSpace.ItemSet.ItemRecByCode(
    locator.DimensionLayerElement(iItem).Value );
  if (!itemRec.IsBound) return false;
  var meDef = dc.MeasureElementDefinition(meIndex);
  var qty = measure.Value(meIndex);
  if( qty == undefined || !util.IsDoubleNormal(qty) ) {
    qty = 0.0;
    measure.Value(meIndex) = 0.0; // 値isDeleteされたら強制的に0に
  }
  // 該当するオーダーAdded・更新・Delete
  var code = itemRec.Code + "-" + util.FormatTime(time, "%y%m%d");
  var orderRec = sdSpace.OrderSet.OrderRecByCode(code);
  if( orderRec.IsBound ) orderRec.Qty = qty;
  else if( qty > 0.0 ) {
    orderRec = sdSpace.OrderSet.OrderRecByCode(code);
    if (!orderRec.IsBound) {
      orderRec = sdSpace.OrderSet.CreateOrderRec(SData.SDOTypeProduction, code);
      orderRec.ItemRec = itemRec;
      orderRec.AssignmentMethod = SData.SDTDirectionBackward;
      orderRec.Color = itemRec.Color;
      orderRec.LatestEndTime = time;
    }
    orderRec.Qty = qty;
  }
  // 関連する値to変える
  var code = itemRec.Comment("mtrl");
  if( code != "" ) itemRec = sdSpace.ItemSet.ItemRecByCode(code);
  UpdateValuesForIntermediateItem(dc, project, itemRec);
  // 不要になったオーダーtoDelete
  if( orderRec.IsBound && orderRec.Qty == 0.0 ) orderRec.Delete();
  editor.Project.FireEvent(FSEditor.FSEEventOrderRecsAreUpdated);
}

// リSchedulingされた
function _Update(keyEntity) {
  var project = keyEntity.ParamObject(FLEXSCHE.ParamIDProject);
  var views = project.views;
  var c = views.CountOfViews;
  for( var i = 0; i < c; i++ ) {
    var view = views.View(i);
    if( view.ViewType != FSVTypeCtrlView ) continue;
    if( view.SpecificationKey != "FSEditor.DataCubeEditor" ) continue;
    var dc = view.Control.DataCube;
    UpdateValues(dc, project);
  }
}

/***************************************************************************************/

// 与えられたData Cubeのすべての値to更新する
function UpdateValues(dc, project) {
  var sdSpace = project.DataSpace;
  if( dc == null ) return;
  // クリア
  dc.ClearMeasures();
  // 要求量
  UpdateValuesForRequired(dc, project);
  // 生産量
  UpdateValuesForProduction(dc, project, null);
  // 生産量調整 - 要求量調整後にSchedulingしていNo分の仮反映
  UpdateValuesForProductionAdjust(dc, project, null);
  // Nakata間品の残量andProductの要求上限
  var dimItem = dc.DimensionByName("Item");
  var layerItemIntermediate = dimItem.LayerByName("intermediate");
  var cIntermediateElems = layerItemIntermediate.CountOfElements;
  for( var iIntermediateElem = 0;
    iIntermediateElem < cIntermediateElems; iIntermediateElem++ ) {
    var elem = layerItemIntermediate.ElementByIndex(iIntermediateElem);
    var intermediateItemRec = sdSpace.ItemSet.ItemRecByCode(elem.Value);
    if (!intermediateItemRec.IsBound) continue;
    UpdateValuesForStock(dc, project, elem, intermediateItemRec);
  }
}

// 部分更新 - 与えられたNakata間品andその関連Productの値to更新する
// Efficiency Improvementのため別に実装した
function UpdateValuesForIntermediateItem(dc, project, intermediateItemRec) {
  var sdSpace = project.DataSpace;
  var cItems = sdSpace.ItemSet.CountOfRecords;
  for( var iItem = 0; iItem < cItems; iItem++ ) {
    var itemRec = sdSpace.ItemSet.ItemRec(iItem);
    if( !itemRec.IsBound || itemRec.IsGroup) continue;
    if( (itemRec.Role & SData.SDIRoleIntermediate) == 0 &&
      (itemRec.Role & SData.SDIRoleFinal) == 0 )
      continue;
    if( itemRec.RecordKey != intermediateItemRec.RecordKey &&
      itemRec.Comment("mtrl") != intermediateItemRec.Code )
      continue;
    // 生産量
    UpdateValuesForProduction(dc, project, itemRec);
    // 生産量調整 - 要求量調整後にSchedulingしていNo分の仮反映
    UpdateValuesForProductionAdjust(dc, project, itemRec);
  }
  // Nakata間品の残量andProductの要求上限
  var dimItem = dc.DimensionByName("Item");
  var layerItemIntermediate = dimItem.LayerByName("intermediate");
  var elem = layerItemIntermediate.ElementByValue(intermediateItemRec.Code);
  UpdateValuesForStock(dc, project, elem, intermediateItemRec);
}

// 要求量 - すべてのオーダーの数量to拾い集める
function UpdateValuesForRequired(dc, project) {
  var iRequired = dc.MeasureElementIndexByName("Required");
  var expFloor = project.DataSpace.CreateTypedExpression(
    SData.SDVTypeTime, SData.SDVTypeTime );
  expFloor.Parse(".Floor");
  var layerTime = dc.DimensionByName("Time").PrimitiveLayer;
  var layerIntermediate = dc
    .DimensionByName("Item")
    .LayerByName("intermediate");
  var layerProduct = dc.DimensionByName("Item").PrimitiveLayer;
  var loc = dc.CreateLocator();
  var orderSet = project.DataSpace.OrderSet;
  var cOrders = orderSet.CountOfRecords;
  for( var iOrder = 0; iOrder < cOrders; iOrder++ ) {
    var orderRec = orderSet.OrderRec(iOrder);
    var itemRec = orderRec.ItemRec;
    var qty = orderRec.Qty;
    var time = expFloor.CalculateFor(orderRec.LatestEndTime);
    loc.SetDimensionLayerElement(layerTime.ElementByValue(time));
    var elem = itemRec.Role & SData.SDIRoleIntermediate
        ? layerIntermediate.ElementByValue(itemRec.Code)
        : layerProduct.ElementByValue(itemRec.Code);
    loc.SetDimensionLayerElement(elem);
    loc.ObtainMeasure().Value(iRequired) = qty;
  }
}

// 生産量 - 品目to特定しNo場合は全品目
function UpdateValuesForProduction(dc, project, targetItemRec) {
  var sdSpace = project.DataSpace;
  var itemSet = sdSpace.ItemSet;
  var cItems = itemSet.CountOfRecords;
  var layerTime = dc.DimensionByName("Time").PrimitiveLayer;
  var layerIntermediate = dc.DimensionByName("Item").LayerByName("intermediate");
  var layerProduct = dc.DimensionByName("Item").PrimitiveLayer;
  var iProduce = dc.MeasureElementIndexByName("Produce");
  var loc = dc.CreateLocator();
  var exp = project.DataSpace.CreateTypedExpression(
    SData.SDVTypeItemRec, SData.SDVTypeVariantList );
  exp.Parse(
    "TimeList.MakeInRange(Project.HorizonStart,Project.HorizonEnd)"
    + ".Convert([$$_object.InventorySubtotalQty(InventoryPCType"
    +".Produce,$_object,$_object+#P1D#,false)])" );
  for( var iItem = 0; iItem < cItems; iItem++ ) {
    var itemRec =
      targetItemRec == null ? itemSet.ItemRec(iItem) : targetItemRec;
    if( itemRec.IsGroup ) continue;
    var layer = itemRec.Role & SData.SDIRoleIntermediate
        ? layerIntermediate : layerProduct;
    var itemElem = layer.ElementByValue(itemRec.Code);
    if( itemElem == null ) continue;
    loc.SetDimensionLayerElement(itemElem);
    var qtyList = exp.CalculateFor(itemRec);
    // Data Cubeに格納
    var c = qtyList.Count;
    for( var i = 0; i < c; i++ ) {
      loc.SetDimensionLayerElement(layerTime.ElementByIndex(i));
      loc.ObtainMeasure().Value(iProduce) = qtyList.Value(i);
    }
    if( targetItemRec != null ) break;
  }
}

// 生産量調整 - 要求量調整後にSchedulingしていNo分の仮反映
function UpdateValuesForProductionAdjust(dc, project, targetItemRec) {
  var sdSpace = project.DataSpace;
  var orderSet = sdSpace.OrderSet;
  var cOrders = orderSet.CountOfRecords;
  var expQty = sdSpace.CreateTypedExpression( SData.SDVTypeOrderRec, SData.SDVTypeDouble );
  expQty.Parse( ".Qty"
    + " - ( ( .Operation.DoesExist and .Operation.IsAssigned ) ? .Operation.LinkQty : 0.0 )" );
  var expIndex = sdSpace.CreateTypedExpression(
    SData.SDVTypeOrderRec, SData.SDVTypeLong );
  expIndex.Parse("( .LatestEndTime - Project.HorizonStart ).Days");
  var loc = dc.CreateLocator();
  var layerTime = dc.DimensionByName("Time").PrimitiveLayer;
  var layerIntermediate = dc.DimensionByName("Item").LayerByName("intermediate");
  var layerProduct = dc.DimensionByName("Item").PrimitiveLayer;
  var iProduce = dc.MeasureElementIndexByName("Produce");
  var iVirtual = dc.MeasureElementIndexByName("Virtual");
  // 品目is指定されている場合は仮想生産量toクリアする
  if( targetItemRec != null ) {
    var layer = targetItemRec.Role & SData.SDIRoleIntermediate
        ? layerIntermediate : layerProduct;
    loc.SetDimensionLayerElement(layer.ElementByValue(targetItemRec.Code));
    loc.SetMeasureValues(iVirtual, 0.0); // まandめてクリア
  }
  // オーダーtoスキャン
  for (var iOrder = 0; iOrder < cOrders; iOrder++) {
    var orderRec = orderSet.OrderRec(iOrder);
    if( !orderRec.IsBound ) continue;
    var itemRec = orderRec.ItemRec;
    if( targetItemRec != null && itemRec.RecordKey != targetItemRec.RecordKey )
      continue;
    var qty = expQty.CalculateFor(orderRec);
    if( qty == 0.0 ) continue;
    var index = expIndex.CalculateFor(orderRec);
    if( index < 0 ) continue;
    var layer = itemRec.Role & SData.SDIRoleIntermediate
        ? layerIntermediate : layerProduct;
    var itemElem = layer.ElementByValue(itemRec.Code);
    if( itemElem == null ) continue;
    loc.SetDimensionLayerElement(itemElem);
    loc.SetDimensionLayerElement(layerTime.ElementByIndex(index));
    loc.ObtainMeasure().Value(iVirtual) = qty;
    var v = loc.ObtainMeasure().Value(iProduce);
    loc.ObtainMeasure().Value(iProduce) = v == undefined ? qty : qty + v;
  }
}

// Nakata間品の残量andProductの要求上限
function UpdateValuesForStock( dc, project, intermediateElem, intermediateItemRec ) {
  var sdSpace = project.DataSpace;
  var sdlUtil = project.Application.CreateCOMInstance("SDLib.SDLUtility");
  var exp = sdSpace.CreateTypedExpression( SData.SDVTypeItemRec, SData.SDVTypeVariantList );
  exp.Parse( "TimeList.MakeInRange(Project.HorizonStart,Project.HorizonEnd)"
    + ".Convert([$$_object.InventoryQty($_object,false)])" );
  var qtyList = exp.CalculateFor(intermediateItemRec);
  var layerTime = dc.DimensionByName("Time").PrimitiveLayer;
  var cTimes = layerTime.CountOfElements;
  var loc = dc.CreateLocator();
  var iStock = dc.MeasureElementIndexByName("Stock");
  var iVirtual = dc.MeasureElementIndexByName("Virtual");
  var iLimit = dc.MeasureElementIndexByName("Limit");
  var iRequired = dc.MeasureElementIndexByName("Required");
  // 子ProductList
  var children = [];
  var cChildren = intermediateElem.CountOfChildren;
  for( var iChild = 0; iChild < cChildren; iChild++ ) {
    var child = intermediateElem.Child(iChild);
    var itemRec = sdSpace.ItemSet.ItemRecByCode(child.Value);
    var ratio = itemRec.SpecCollection.NumSpec("ratio");
    ratio = sdlUtil.IsDoubleNormal(ratio) ? ratio : 1.0;
    children.push({ child: child, ratio: ratio });
  }
  // Nakata間品の残量
  var virtualQty = 0.0;
  loc.SetDimensionLayerElement(intermediateElem);
  var locChild = dc.CreateLocator();
  for( var iTime = 0; iTime < cTimes; iTime++ ) {
    var timeElem = layerTime.ElementByIndex(iTime);
    loc.SetDimensionLayerElement(timeElem);
    locChild.SetDimensionLayerElement(timeElem);
    virtualQty += loc.ObtainMeasure().Value(iVirtual);
    var cChildren = children.length;
    for (var iChild = 0; iChild < cChildren; iChild++) {
      var v = children[iChild];
      locChild.SetDimensionLayerElement(v.child);
      virtualQty -= locChild.ObtainMeasure().Value(iVirtual) * v.ratio;
    }
    loc.ObtainMeasure().Value(iStock) = qtyList.Value(iTime) + virtualQty;
  }
  // Productの要求上限
  var cChildren = children.length;
  for( var iChild = 0; iChild < cChildren; iChild++ ) {
    var v = children[iChild];
    locChild.SetDimensionLayerElement(v.child);
    var futureMin = 9999999.9;
    for( var iTime = cTimes - 1; iTime >= 0; iTime-- ) {
      var timeElem = layerTime.ElementByIndex(iTime);
      loc.SetDimensionLayerElement(timeElem);
      locChild.SetDimensionLayerElement(timeElem);
      var qty = loc.MeasureValue(iStock);
      if( futureMin > qty ) futureMin = qty;
      var req = locChild.MeasureValue(iRequired);
      var q = Math.floor(futureMin / v.ratio) + req;
      locChild.ObtainMeasure().Value(iLimit) = q < 0.0 ? 0.0 : q;
    }
  }
}

/***************************************************************************************/
// generated by WSCGEN

function Setup(keyEntity) {
  ret = _Setup(keyEntity);
  CollectGarbage();
  return ret;
}
function Command(keyEntity) {
  ret = _Command(keyEntity);
  CollectGarbage();
  return ret;
}
function ObtainDatacube(keyEntity) {
  ret = _ObtainDatacube(keyEntity);
  CollectGarbage();
  return ret;
}
function ValueChanged(keyEntity) {
  ret = _ValueChanged(keyEntity);
  CollectGarbage();
  return ret;
}
function Rescheduled(keyEntity) {
  ret = _Update(keyEntity);
  CollectGarbage();
  return ret;
}
function AfterLoadingData(keyEntity) {
  ret = _Update(keyEntity);
  CollectGarbage();
  return ret;
}
function VBDateFromJDate(d) {
  return Script.VBDateFromSeconds(
    d.getTime() / 1000 - d.getTimezoneOffset() * 60
  );
}
function VBDateFromLiteral(str) {
  var d = new Date(str);
  return Script.VBDateFromSeconds(
    d.getTime() / 1000 - d.getTimezoneOffset() * 60
  );
}
function VBDateToJDate(t) {
  d = new Date();
  d.setTime(Script.VBDateToSeconds(t) * 1000 + d.getTimezoneOffset() * 60000);
  return d;
}
function alert(msg) {
  Script.ShowMessageBox(msg, "FLEXSCHE", AIM.MBTOk);
}

Check-out by Item Unit in d-MPS on Communicator

When using FLEXSCHE d-MPS in a Communicator project, it is now possible to edit MPS data by checking out records on an item basis. Previously, it was necessary to check out the entire dataset, allowing only one person to edit at a time. Now, even if different people are responsible for different items, editing can be done smoothly.

Introduction to FLEXSCHE Products

PAGETOP