From 70aa430bdb228d6193286faa437dd5b90366c6ea Mon Sep 17 00:00:00 2001
From: rislai <risheng.lai@capgemini.com>
Date: 星期六, 22 六月 2024 03:31:30 +0800
Subject: [PATCH] 添加需求版本对比功能

---
 _Main/BL/Type_LocalCell_DemandComparison/StaticMethod_AsyncExport.qbl                                                                          |   31 ++
 _Main/BL/Type_LocalCell_DemandComparison/Function_CalcGap.qbl                                                                                  |   13 +
 _Main/BL/Type_LocalRow/Attribute_CustomName.qbl                                                                                                |    7 
 _Main/BL/Type_LocalCell_DemandComparison/Attribute_BaseVersion.qbl                                                                             |    7 
 _Main/BL/Type_LocalColumn/Attribute_IsAttrbuteColumn.qbl                                                                                       |    7 
 _Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Response_PanelOperation_ButtonCompare_OnClick.def                                   |    4 
 _Main/BL/Type_ArchivePR/StaticMethod_FillCells.qbl                                                                                             |   30 ++
 _Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Component_PanelOperation.def                                                        |    3 
 _Main/BL/Type_ExportXMLManager/Method_Export.qbl                                                                                               |    9 
 _Main/BL/Type_LocalCell_DemandComparison/Method_GetAttributeByName.qbl                                                                         |   44 +++
 _Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Component_pOperation#715.def                                                        |   63 ++++
 _Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Response_PanelOperation11_DropDownListCompareVersion_OnSelectionChanged.def         |   18 +
 _Main/BL/Type_Test/StaticMethod_Test.qbl                                                                                                       |   34 ++
 _Main/BL/Type_ExportXMLManager/StaticMethod_AwaitShiftPlanXMLData.qbl                                                                          |    1 
 _Main/UI/MacroPlannerWebApp/Component_ApplicationMacroPlanner/_ROOT_Component_ApplicationMacroPlanner.def                                      |    1 
 _Main/BL/Type_LocalCell_DemandComparison/Attribute_CompareVersionValue.qbl                                                                     |    7 
 _Main/BL/Type_ExportXMLManager/StaticMethod_AwaitLocalTableXMLData.qbl                                                                         |   36 ++
 _Main/UI/MacroPlannerWebApp/Views/DemandComparison.vw                                                                                          |   16 +
 _Main/BL/Type_LocalRow/Attribute_Name.qbl                                                                                                      |    7 
 _Main/BL/Type_LocalRow/Function_CalcName.qbl                                                                                                   |   13 +
 _Main/UI/MacroPlannerWebApp/Component_ApplicationMacroPlanner/Component_ActionBarGroupScenarioComparisonViews#859.def                          |   18 +
 _Main/UI/MacroPlannerWebApp/Component_ApplicationMacroPlanner/Response_MacroPlanner_ActionBarGroupScenarioComparisonViews_ButtonScenarioCo.def |   17 +
 _Main/BL/Type_LocalCell_DemandComparison/StaticMethod_GetColumnXML.qbl                                                                         |   56 ++++
 _Main/BL/Type_ArchivePR/StaticMethod_Compared.qbl                                                                                              |  105 +++++++
 _Main/BL/Type_LocalCell_DemandComparison/Attribute_Gap.qbl                                                                                     |    7 
 _Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Component_PanelOperation11.def                                                      |    4 
 _Main/BL/Type_LocalTable/Attribute_Name.qbl                                                                                                    |    7 
 _Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Response_pOperation_715_bExport_OnClick.def                                         |   18 +
 /dev/null                                                                                                                                      |    7 
 _Main/UI/MacroPlannerWebApp/Component_ApplicationMacroPlanner/Response_MacroPlanner_ActionBarGroupDebug_ButtonTest_OnClick.def                 |    4 
 _Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Response_PanelOperation11_DropDownListBaseVersion_OnSelectionChanged#168.def        |    1 
 _Main/BL/Type_ArchivePR/StaticMethod_GenerateColumnIndex.qbl                                                                                   |   39 +++
 _Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Response_PanelDemandComparison_dhComparisonData_OnDataChanged.def                   |   16 +
 _Main/BL/Type_ArchivePR/StaticMethod_FillRows.qbl                                                                                              |   36 ++
 _Main/UI/MacroPlannerWebApp/Component_ApplicationMacroPlanner/Component_ActionBarPageScenarioComparison.def                                    |    8 
 _Main/BL/Type_LocalCell_DemandComparison/StaticMethod_GetAttributeNames.qbl                                                                    |   18 +
 _Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Response_pOperation_715_bDownload_OnClick.def                                       |   30 ++
 _Main/BL/Type_LocalCell_DemandComparison/Attribute_CompareVersion.qbl                                                                          |    7 
 _Main/BL/Type_LocalCell_DemandComparison/Attribute_BaseVersionValue.qbl                                                                        |    7 
 _Main/UI/MacroPlannerWebApp/Component_Form568/Response_pOperation_bDownload_OnClick.def                                                        |    2 
 _Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Component_MatrixEditor.def                                                          |    7 
 _Main/BL/Type_LocalCell_DemandComparison/_ROOT_Type_LocalCell_DemandComparison.qbl                                                             |    9 
 42 files changed, 744 insertions(+), 30 deletions(-)

diff --git a/_Main/BL/Type_ArchivePR/Method_Load.qbl b/_Main/BL/Type_ArchivePR/Method_Load.qbl
deleted file mode 100644
index e116a1e..0000000
--- a/_Main/BL/Type_ArchivePR/Method_Load.qbl
+++ /dev/null
@@ -1,67 +0,0 @@
-Quintiq file version 2.0
-#parent: #root
-Method Load (
-  LocalTable localTable
-) const
-{
-  TextBody:
-  [*
-    // rislai Jun-20-2024 (created)
-    file := OSFile::Construct();
-    recycleBin := localTable.RecycleBin();
-    
-    columns := selectset( localTable,LocalColumn,column,true );
-    columnTree := NamedValueTree::Create();
-    for( i := 0 ; i < columns.Size(); i++ ){
-      column := columns.Element( i );
-      tempHandle := columnTree.GetHandle( column.Name() );
-      columnTree.Root().AddChild( tempHandle,i );
-    }
-    
-    try {
-      file.Open( this.FilePath(), "Read", false );
-      webFileBinaryData := file.ReadBinary();
-        
-      generalExcelImportAndExportDataSource := GeneralExcelImportAndExportDataSource::Upload( recycleBin, webFileBinaryData, this.Name() );
-      generalExcelImportAndExportDataSource.ReadStructure();
-      selections := selectset( generalExcelImportAndExportDataSource, GeneralExcelImportAndExportDataTable, tempGEIAEDT, true );
-      if( selections.Size() <> 0 ){
-        table := selections.Element( 0 );
-        generalColumns := selectset( table,GeneralExcelImportAndExportDataColumn,column,true );
-        
-        // 鐢熸垚鍒楁暟鎹�
-        for( i := 0; i< generalColumns.Size(); i++ ){
-          generalColumn := generalColumns.Element( i );
-          column := localTable.LocalColumn( relnew, Name := generalColumn.Name(),Index := generalColumn.ColumnIndex() );
-          columns.Add( column );
-          tempHandle := columnTree.GetHandle( column.Name() );
-          columnTree.Root().AddChild( tempHandle,columns.Size() - 1 );
-        }
-        
-        // 鐢熸垚鏁版嵁
-        rowSize := table.GeneralExcelImportAndExportDataRow( relsize );
-        for ( rowIndex := 0; rowIndex < rowSize; rowIndex++ ) {
-          generalRow := select( table, GeneralExcelImportAndExportDataRow, tempGEIAEDR, tempGEIAEDR.RowNr() = rowIndex );
-          row := localTable.LocalRow( relnew,Index := rowIndex );
-          generalCells := selectsortedset( generalRow,GeneralExcelImportAndExportDataCell,cell,true,cell.GeneralExcelImportAndExportDataColumn().ColumnIndex() );
-          
-          traverse( generalCells,Elements,generalCell ){
-            columnName := generalCell.GeneralExcelImportAndExportDataColumn().Name();
-            columnHandle := columnTree.GetHandle( columnName );
-            columnIndex := columnTree.Root().Child( columnHandle ).GetValueAsNumber();
-            column := columns.Element( columnIndex );
-            row.LocalCell( relnew,Value := generalCell.Value() ,LocalColumn := column );
-          }
-        }
-      }
-      // 鍚庣画鍒犻櫎
-      generalExcelImportAndExportDataSource.Delete();
-      file.Close();
-    } onerror {
-      if( not isnull( file )){
-        file.Close(); 
-      }
-      error( e );
-    }
-  *]
-}
diff --git a/_Main/BL/Type_ArchivePR/StaticMethod_Compared.qbl b/_Main/BL/Type_ArchivePR/StaticMethod_Compared.qbl
index a6be942..75469e5 100644
--- a/_Main/BL/Type_ArchivePR/StaticMethod_Compared.qbl
+++ b/_Main/BL/Type_ArchivePR/StaticMethod_Compared.qbl
@@ -9,13 +9,108 @@
   TextBody:
   [*
     // rislai Jun-20-2024 (created)
-    // archive := baseVersion.Archive(); // archive涓嶅彲璁剧疆涓哄彧璇�
+    localTable := recycleBin.LocalTable( relnew,Name := baseVersion.Name() + "__" + compareVersion.Name());
     
-    table := recycleBin.LocalTable( relnew );
+    baseVersionFile := OSFile::Construct();
+    compareVersionFile := OSFile::Construct();
     
-    baseVersion.Load( table ); 
-    compareVersion.Load( table ); 
+    try {
+      baseVersionFile.Open( baseVersion.FilePath(), "Read", false );
+      baseVersionDataSource := GeneralExcelImportAndExportDataSource::Upload( recycleBin, baseVersionFile.ReadBinary(), baseVersion.FilePath() );
+      baseVersionDataSource.ReadStructure();
+      
+      compareVersionFile.Open( compareVersion.FilePath(), "Read", false );
+      compareVersionDataSource := GeneralExcelImportAndExportDataSource::Upload( recycleBin, compareVersionFile.ReadBinary(), compareVersion.FilePath() );
+      compareVersionDataSource.ReadStructure();
+      
+      baseVersionTable := select( baseVersionDataSource, GeneralExcelImportAndExportDataTable, tempGEIAEDT, true );
+      compareVersionTable := select( compareVersionDataSource, GeneralExcelImportAndExportDataTable, tempGEIAEDT, true );
+      
+      if( not isnull( baseVersionTable ) and not isnull( compareVersionTable )){
+        
+        //鐢熸垚琛屾暟鎹�
+        rowKeys := construct( Strings );
+        baseVersionRowTree := NamedValueTree::Create();
+        baseVersionRows := construct( GeneralExcelImportAndExportDataRows ,constcontent);
+        compareVersionRowTree := NamedValueTree::Create();
+        compareVersionRows := construct( GeneralExcelImportAndExportDataRows ,constcontent);
+        ArchivePR::FillRows( baseVersionTable,rowKeys,baseVersionRowTree,baseVersionRows );
+        ArchivePR::FillRows( compareVersionTable,rowKeys,compareVersionRowTree,compareVersionRows );
+        
+        // 鐢熸垚鍒楁暟鎹�
+        columnTree := NamedValueTree::Create();
+        columns := construct( LocalColumns );
+        ArchivePR::GenerateColumnIndex( baseVersionTable,localTable,columnTree,columns );
+        ArchivePR::GenerateColumnIndex( compareVersionTable,localTable,columnTree,columns );
+        columnNames := selectvalues( columns,Elements,column,true,column.Name() );
+        
+        // 鐢熸垚鏁版嵁
+        
+        for ( rowIndex := 0; rowIndex < rowKeys.Size(); rowIndex++ ) {
+          rowKey := rowKeys.Element( rowIndex );
+          
+          baseVersionCellTree := NamedValueTree::Create();
+          baseVersionCells := construct( GeneralExcelImportAndExportDataCells ,constcontent);
+          
+          compareVersionCellTree := NamedValueTree::Create();
+          compareVersionCells := construct( GeneralExcelImportAndExportDataCells ,constcontent);
+          
+          ArchivePR::FillCells( rowKey,baseVersionRowTree,baseVersionRows,baseVersionCellTree,baseVersionCells );
+          ArchivePR::FillCells( rowKey,compareVersionRowTree,compareVersionRows,compareVersionCellTree,compareVersionCells );
+          
+          row := localTable.LocalRow( relnew,Index := localTable.GetRowIndexCache()  );
+          
+          traverse( columnNames,Elements,columnName ){
+            columnHandle := columnTree.GetHandle( columnName );
+            columnIndex := columnTree.Root().Child( columnHandle ).GetValueAsNumber();
+            column := columns.Element( columnIndex );
+            
+            baseVersionCell := constnull( GeneralExcelImportAndExportDataCell );
+            baseVersionCellHandle := baseVersionCellTree.GetHandle( columnName );
+            try{
+              baseVersionCellIndex := baseVersionCellTree.Root().Child( baseVersionCellHandle ).GetValueAsNumber();
+              baseVersionCell := baseVersionCells.Element( baseVersionCellIndex );
+            }onerror{}
+            
+            compareVersionCell := constnull( GeneralExcelImportAndExportDataCell );
+            compareVersionCellHandle := compareVersionCellTree.GetHandle( columnName );
+            try{
+              compareVersionCellIndex := compareVersionCellTree.Root().Child( compareVersionCellHandle ).GetValueAsNumber();
+              compareVersionCell := compareVersionCells.Element( compareVersionCellIndex );
+            }onerror{}
+            
+            if( columnName = "浜у湴" or columnName = "杞﹀瀷" or columnName = "鍙戝姩鏈洪浂浠跺彿" or columnName = "鍙戝姩鏈哄洓浣嶇爜" ){
+              row.LocalCell( relnew,LocalCell_DemandComparison,LocalColumn := column,
+                             BaseVersionValue := ifexpr( isnull( baseVersionCell ), "绌�", baseVersionCell.Value()),
+                             CompareVersionValue := ifexpr( isnull( compareVersionCell ),"绌�",compareVersionCell.Value()));
+              column.IsAttrbuteColumn( true );
+              if( columnName = "鍙戝姩鏈洪浂浠跺彿" ){
+                row.CustomName( ifexpr( isnull( baseVersionCell ), ifexpr( isnull( compareVersionCell ),"绌�",compareVersionCell.Value()), baseVersionCell.Value()) );
+              }
+            }else{
+              row.LocalCell( relnew,LocalCell_DemandComparison,LocalColumn := column,
+                             BaseVersion := ifexpr( isnull( baseVersionCell ),0,[Real]baseVersionCell.Value()),
+                             CompareVersion := ifexpr( isnull( compareVersionCell ), 0 ,[Real]compareVersionCell.Value() ));
+            }
+          }
+        }
+      }
+      // 鍚庣画鍒犻櫎
+      baseVersionDataSource.Delete();
+      compareVersionDataSource.Delete();
+      
+      baseVersionFile.Close();
+      compareVersionFile.Close();
+    } onerror {
+      if( not isnull( baseVersionFile )){
+        baseVersionFile.Close(); 
+      }
+      if( not isnull( compareVersionFile )){
+        compareVersionFile.Close(); 
+      }
+      error( e );
+    }
     
-    return table;
+    return localTable;
   *]
 }
diff --git a/_Main/BL/Type_ArchivePR/StaticMethod_FillCells.qbl b/_Main/BL/Type_ArchivePR/StaticMethod_FillCells.qbl
new file mode 100644
index 0000000..6aeded1
--- /dev/null
+++ b/_Main/BL/Type_ArchivePR/StaticMethod_FillCells.qbl
@@ -0,0 +1,30 @@
+Quintiq file version 2.0
+#parent: #root
+StaticMethod FillCells (
+  String rowName,
+  NamedValueTree rowTree,
+  constcontent GeneralExcelImportAndExportDataRows rows,
+  NamedValueTree cellTree,
+  constcontent GeneralExcelImportAndExportDataCells cells
+)
+{
+  TextBody:
+  [*
+    // rislai Jun-22-2024 (created)
+    rowHandel := rowTree.GetHandle( rowName );
+    try{
+      rowIndex := rowTree.Root().Child( rowHandel ).GetValueAsNumber();
+      row := rows.Element( rowIndex );
+      
+      temp_cells := selectsortedset( row,GeneralExcelImportAndExportDataCell,cell,true,cell.GeneralExcelImportAndExportDataColumn().ColumnIndex() );
+      for( i := 0 ; i<temp_cells.Size();i++ ){
+        cell := temp_cells.Element( i );
+        tempHandle := cellTree.GetHandle( cell.GeneralExcelImportAndExportDataColumn().Name() );
+        
+        cells.Add( cell );
+        cellTree.Root().AddChild( tempHandle,cells.Size() - 1 );
+        
+      }
+    }onerror{}
+  *]
+}
diff --git a/_Main/BL/Type_ArchivePR/StaticMethod_FillRows.qbl b/_Main/BL/Type_ArchivePR/StaticMethod_FillRows.qbl
new file mode 100644
index 0000000..391100a
--- /dev/null
+++ b/_Main/BL/Type_ArchivePR/StaticMethod_FillRows.qbl
@@ -0,0 +1,36 @@
+Quintiq file version 2.0
+#parent: #root
+StaticMethod FillRows (
+  const GeneralExcelImportAndExportDataTable general,
+  Strings rowKeys,
+  NamedValueTree rowTree,
+  constcontent GeneralExcelImportAndExportDataRows rows
+)
+{
+  TextBody:
+  [*
+    // rislai Jun-22-2024 (created)
+    rowKeyColumn1 := select( general, GeneralExcelImportAndExportDataColumn, column, column.Name() = "浜у湴" );
+    rowKeyColumn2 := select( general, GeneralExcelImportAndExportDataColumn, column, column.Name() = "杞﹀瀷" );
+    rowKeyColumn3 := select( general, GeneralExcelImportAndExportDataColumn, column, column.Name() = "鍙戝姩鏈洪浂浠跺彿" );
+    rowKeyColumn4 := select( general, GeneralExcelImportAndExportDataColumn, column, column.Name() = "鍙戝姩鏈哄洓浣嶇爜" );
+    tempRowKeyCells1 := selectset( rowKeyColumn1,GeneralExcelImportAndExportDataCell,cell,true );
+    tempRowKeyCells2 := selectset( rowKeyColumn2,GeneralExcelImportAndExportDataCell,cell,true );
+    tempRowKeyCells3 := selectset( rowKeyColumn3,GeneralExcelImportAndExportDataCell,cell,true );
+    tempRowKeyCells4 := selectset( rowKeyColumn4,GeneralExcelImportAndExportDataCell,cell,true );
+    
+    for( i := 0; i< tempRowKeyCells1.Size(); i++ ){
+      tempRowKeyCell1 := tempRowKeyCells1.Element( i );
+      tempRowKeyCell2 := tempRowKeyCells2.Element( i );
+      tempRowKeyCell3 := tempRowKeyCells3.Element( i );
+      tempRowKeyCell4 := tempRowKeyCells4.Element( i );
+      
+      rowKey := tempRowKeyCell1.Value() + tempRowKeyCell2.Value() + tempRowKeyCell3.Value() + tempRowKeyCell4.Value();
+      
+      tempHandle := rowTree.GetHandle( rowKey );
+      rowTree.Root().AddChild( tempHandle ,i);
+      rows.Add( tempRowKeyCell1.GeneralExcelImportAndExportDataRow());
+      rowKeys.Add( rowKey );
+    }
+  *]
+}
diff --git a/_Main/BL/Type_ArchivePR/StaticMethod_GenerateColumnIndex.qbl b/_Main/BL/Type_ArchivePR/StaticMethod_GenerateColumnIndex.qbl
new file mode 100644
index 0000000..5bdd4f8
--- /dev/null
+++ b/_Main/BL/Type_ArchivePR/StaticMethod_GenerateColumnIndex.qbl
@@ -0,0 +1,39 @@
+Quintiq file version 2.0
+#parent: #root
+StaticMethod GenerateColumnIndex (
+  const GeneralExcelImportAndExportDataTable table,
+  LocalTable localTable,
+  NamedValueTree columnTree,
+  LocalColumns columns
+)
+{
+  TextBody:
+  [*
+    // rislai Jun-22-2024 (created)
+    tableColumns := selectset( table,GeneralExcelImportAndExportDataColumn,column,true );
+    for( i := 0; i< tableColumns.Size(); i++ ){
+      generalColumn := tableColumns.Element( i );
+      tempHandle := columnTree.GetHandle( generalColumn.Name() );
+    
+      nameValue := guard( columnTree.Root().Child( tempHandle ),null( NamedValue )); 
+      if( isnull( nameValue )){
+        index := 999;
+        if( generalColumn.Name() = "浜у湴" ){
+          index := 1;
+        }else if( generalColumn.Name() = "杞﹀瀷" ){
+          index := 2;
+        }else if( generalColumn.Name() = "鍙戝姩鏈洪浂浠跺彿" ){
+          index := 3;
+        }else if( generalColumn.Name() = "鍙戝姩鏈哄洓浣嶇爜" ){
+          index := 4;
+        }else{
+          // 2023/01/01
+          index := [Number]generalColumn.Name().ReplaceAll( "/", "" );
+        }
+        column := localTable.LocalColumn( relnew, Name := generalColumn.Name(),Index := index );
+        columns.Add( column );
+        columnTree.Root().AddChild( tempHandle,columns.Size() - 1 );
+      }
+    }
+  *]
+}
diff --git a/_Main/BL/Type_ShiftPlan/StaticMethod_Export.qbl b/_Main/BL/Type_ExportXMLManager/Method_Export.qbl
similarity index 71%
rename from _Main/BL/Type_ShiftPlan/StaticMethod_Export.qbl
rename to _Main/BL/Type_ExportXMLManager/Method_Export.qbl
index 6883630..76e648d 100644
--- a/_Main/BL/Type_ShiftPlan/StaticMethod_Export.qbl
+++ b/_Main/BL/Type_ExportXMLManager/Method_Export.qbl
@@ -1,15 +1,12 @@
 Quintiq file version 2.0
 #parent: #root
-StaticMethod Export (
-  const ExportXMLManager manager
-) as BinaryValue
+Method Export () as BinaryValue
 {
   TextBody:
   [*
-    // rislai Jun-20-2024 (created)
-     
+    // rislai Jun-21-2024 (created)
     tableGroupHandle := TableGroupHandle::Create( "tableGroupHandle" );
-    tableHandle := TableHandle::ImportXML( BinaryValue::Construct( manager.FinalXML() ) );
+    tableHandle := TableHandle::ImportXML( BinaryValue::Construct( this.FinalXML() ) );
     tableGroupHandle.Add( tableHandle );
     binaryData := XLS::SaveTableGroupToBinaryData( tableGroupHandle, true );
      
diff --git a/_Main/BL/Type_ExportXMLManager/StaticMethod_AwaitLocalTableXMLData.qbl b/_Main/BL/Type_ExportXMLManager/StaticMethod_AwaitLocalTableXMLData.qbl
new file mode 100644
index 0000000..fdde1b7
--- /dev/null
+++ b/_Main/BL/Type_ExportXMLManager/StaticMethod_AwaitLocalTableXMLData.qbl
@@ -0,0 +1,36 @@
+Quintiq file version 2.0
+#parent: #root
+StaticMethod AwaitLocalTableXMLData (
+  const Strings columnXMLData,
+  RecycleBin owner
+)
+{
+  TextBody:
+  [*
+    // rislai Jun-21-2024 (created)
+    manager := select( owner,ExportXMLManager,manager,manager.Name() = "LocalTableXML" );
+    if( isnull( manager )){
+      manager := owner.ExportXMLManager( relnew,Name := "LocalTableXML" );
+    }else{
+      manager.ExportXMLData( relflush );
+    }
+    traverse( columnXMLData,Elements,element,element.TrimBoth() <> "" ){
+       data := manager.ExportXMLData( relnew, XML := element);
+       if( element.LikeUserLocale( "Product ID" )){
+         data.Priority( 1 );
+       }else if( element.LikeUserLocale( "Attribute" )){
+         data.Priority( 2 );
+       }else if( element.LikeUserLocale( "浜у湴" )){
+         data.Priority( 3 );
+       }else if( element.LikeUserLocale( "杞﹀瀷" )){
+         data.Priority( 4 );
+       }else if( element.LikeUserLocale( "鍙戝姩鏈洪浂浠跺彿" )){
+         data.Priority( 5 );
+       }else if( element.LikeUserLocale( "鍙戝姩鏈哄洓浣嶇爜" )){
+         data.Priority( 6 );
+       }else{
+         data.Priority( [Number]element.SubString( 14,10 ).ReplaceAll( "/","") );
+       }
+    }
+  *]
+}
diff --git a/_Main/BL/Type_ExportXMLManager/StaticMethod_AwaitShiftPlanXMLData.qbl b/_Main/BL/Type_ExportXMLManager/StaticMethod_AwaitShiftPlanXMLData.qbl
index 7f10e9c..fc5bb88 100644
--- a/_Main/BL/Type_ExportXMLManager/StaticMethod_AwaitShiftPlanXMLData.qbl
+++ b/_Main/BL/Type_ExportXMLManager/StaticMethod_AwaitShiftPlanXMLData.qbl
@@ -8,7 +8,6 @@
   TextBody:
   [*
     // rislai Jun-20-2024 (created)
-    
     manager := select( owner,ExportXMLManager,manager,manager.Name() = "ShiftPlanXML" );
     if( isnull( manager )){
       manager := owner.ExportXMLManager( relnew,Name := "ShiftPlanXML" );
diff --git a/_Main/BL/Type_LocalCell/Attribute_Value.qbl b/_Main/BL/Type_LocalCell/Attribute_Value.qbl
deleted file mode 100644
index 572510e..0000000
--- a/_Main/BL/Type_LocalCell/Attribute_Value.qbl
+++ /dev/null
@@ -1,7 +0,0 @@
-Quintiq file version 2.0
-#parent: #root
-Attribute Value
-{
-  #keys: '3[412672.0.1086954759][412672.0.1086954758][412672.0.1086954760]'
-  ValueType: String
-}
diff --git a/_Main/BL/Type_LocalCell_DemandComparison/Attribute_BaseVersion.qbl b/_Main/BL/Type_LocalCell_DemandComparison/Attribute_BaseVersion.qbl
new file mode 100644
index 0000000..e4182b7
--- /dev/null
+++ b/_Main/BL/Type_LocalCell_DemandComparison/Attribute_BaseVersion.qbl
@@ -0,0 +1,7 @@
+Quintiq file version 2.0
+#parent: #root
+Attribute BaseVersion
+{
+  #keys: '3[412672.0.1087844729][412672.0.1087844728][412672.0.1087844730]'
+  ValueType: Real
+}
diff --git a/_Main/BL/Type_LocalCell_DemandComparison/Attribute_BaseVersionValue.qbl b/_Main/BL/Type_LocalCell_DemandComparison/Attribute_BaseVersionValue.qbl
new file mode 100644
index 0000000..7084a1a
--- /dev/null
+++ b/_Main/BL/Type_LocalCell_DemandComparison/Attribute_BaseVersionValue.qbl
@@ -0,0 +1,7 @@
+Quintiq file version 2.0
+#parent: #root
+Attribute BaseVersionValue
+{
+  #keys: '3[412672.0.1087874641][412672.0.1087874640][412672.0.1087874642]'
+  ValueType: String
+}
diff --git a/_Main/BL/Type_LocalCell_DemandComparison/Attribute_CompareVersion.qbl b/_Main/BL/Type_LocalCell_DemandComparison/Attribute_CompareVersion.qbl
new file mode 100644
index 0000000..1884719
--- /dev/null
+++ b/_Main/BL/Type_LocalCell_DemandComparison/Attribute_CompareVersion.qbl
@@ -0,0 +1,7 @@
+Quintiq file version 2.0
+#parent: #root
+Attribute CompareVersion
+{
+  #keys: '3[412672.0.1087844726][412672.0.1087844725][412672.0.1087844727]'
+  ValueType: Real
+}
diff --git a/_Main/BL/Type_LocalCell_DemandComparison/Attribute_CompareVersionValue.qbl b/_Main/BL/Type_LocalCell_DemandComparison/Attribute_CompareVersionValue.qbl
new file mode 100644
index 0000000..a1a480c
--- /dev/null
+++ b/_Main/BL/Type_LocalCell_DemandComparison/Attribute_CompareVersionValue.qbl
@@ -0,0 +1,7 @@
+Quintiq file version 2.0
+#parent: #root
+Attribute CompareVersionValue
+{
+  #keys: '3[412672.0.1087874649][412672.0.1087874648][412672.0.1087874650]'
+  ValueType: String
+}
diff --git a/_Main/BL/Type_LocalCell_DemandComparison/Attribute_Gap.qbl b/_Main/BL/Type_LocalCell_DemandComparison/Attribute_Gap.qbl
new file mode 100644
index 0000000..efe049a
--- /dev/null
+++ b/_Main/BL/Type_LocalCell_DemandComparison/Attribute_Gap.qbl
@@ -0,0 +1,7 @@
+Quintiq file version 2.0
+#parent: #root
+Attribute Gap
+{
+  #keys: '3[412672.0.1087844732][412672.0.1087844731][412672.0.1087844733]'
+  ValueType: Real
+}
diff --git a/_Main/BL/Type_LocalCell_DemandComparison/Function_CalcGap.qbl b/_Main/BL/Type_LocalCell_DemandComparison/Function_CalcGap.qbl
new file mode 100644
index 0000000..90a8d2f
--- /dev/null
+++ b/_Main/BL/Type_LocalCell_DemandComparison/Function_CalcGap.qbl
@@ -0,0 +1,13 @@
+Quintiq file version 2.0
+#parent: #root
+Function CalcGap
+{
+  TextBody:
+  [*
+    // rislai Jun-21-2024 (created)
+    
+    value := this.BaseVersion() - this.CompareVersion();
+    
+    this.Gap( value );
+  *]
+}
diff --git a/_Main/BL/Type_LocalCell_DemandComparison/Method_GetAttributeByName.qbl b/_Main/BL/Type_LocalCell_DemandComparison/Method_GetAttributeByName.qbl
new file mode 100644
index 0000000..f51ae7a
--- /dev/null
+++ b/_Main/BL/Type_LocalCell_DemandComparison/Method_GetAttributeByName.qbl
@@ -0,0 +1,44 @@
+Quintiq file version 2.0
+#parent: #root
+Method GetAttributeByName (
+  String attributeName
+) const declarative as String
+{
+  TextBody:
+  [*
+    // rislai Jun-21-2024 (created)
+    value := "";
+    
+    if( attributeName = "BaseVersion" ){
+       if( not this.LocalColumn().IsAttrbuteColumn() ){
+         value := this.BaseVersion().Format( "N(Dec)" );
+       }
+    }
+    if( attributeName = "CompareVersion" ){
+      if( not this.LocalColumn().IsAttrbuteColumn() ){
+        value := this.CompareVersion().Format( "N(Dec)" );
+      }
+    }
+    if( attributeName = "Gap" ){
+      if( not this.LocalColumn().IsAttrbuteColumn() ){
+        value := this.Gap().Format( "N(Dec)" );
+      }
+    }
+    if( attributeName = "BaseVersionValue" ){
+      if( not this.LocalColumn().IsAttrbuteColumn() ){
+        value := "0";
+      }else{
+        value := this.BaseVersionValue();
+      }
+    }
+    if( attributeName = "CompareVersionValue" ){
+      if( not this.LocalColumn().IsAttrbuteColumn() ){
+        value := "0";
+      }else{
+        value := this.CompareVersionValue();
+      }
+    }
+    
+    return value;
+  *]
+}
diff --git a/_Main/BL/Type_LocalCell_DemandComparison/StaticMethod_AsyncExport.qbl b/_Main/BL/Type_LocalCell_DemandComparison/StaticMethod_AsyncExport.qbl
new file mode 100644
index 0000000..4364350
--- /dev/null
+++ b/_Main/BL/Type_LocalCell_DemandComparison/StaticMethod_AsyncExport.qbl
@@ -0,0 +1,31 @@
+Quintiq file version 2.0
+#parent: #root
+StaticMethod AsyncExport (
+  RecycleBin recycleBin,
+  const constcontent LocalRows rows,
+  const constcontent LocalColumns columns
+)
+{
+  TextBody:
+  [*
+    // rislai Jun-20-2024 (created)
+    sortColumns := selectsortedset( columns,Elements,column,true,column.Index());
+    
+    attributeNames := LocalCell_DemandComparison::GetAttributeNames();
+    
+    columnstring := emit( "" );
+    flag := true;
+    traverse( sortColumns,Elements,sortColumn ){
+      if( flag ){
+        attributeXML := rows -> LocalCell_DemandComparison::GetColumnXML( sortColumn,attributeNames,"attribute" );
+        columnstring := columnstring.Merge( attributeXML )
+        flag := false;
+      }
+      
+      cellxml := rows -> LocalCell_DemandComparison::GetColumnXML( sortColumn,attributeNames ,"data");
+      columnstring := columnstring.Merge( cellxml);
+    }
+     
+    columnstring -> GroupAll() -> ExportXMLManager::AwaitLocalTableXMLData( recycleBin );
+  *]
+}
diff --git a/_Main/BL/Type_LocalCell_DemandComparison/StaticMethod_GetAttributeNames.qbl b/_Main/BL/Type_LocalCell_DemandComparison/StaticMethod_GetAttributeNames.qbl
new file mode 100644
index 0000000..24a6087
--- /dev/null
+++ b/_Main/BL/Type_LocalCell_DemandComparison/StaticMethod_GetAttributeNames.qbl
@@ -0,0 +1,18 @@
+Quintiq file version 2.0
+#parent: #root
+StaticMethod GetAttributeNames () const declarative as owning Strings
+{
+  TextBody:
+  [*
+    // rislai Jun-21-2024 (created)
+    attributeNames := construct( Strings );
+    
+    attributeNames.Add( "BaseVersion" );
+    attributeNames.Add( "CompareVersion" );
+    attributeNames.Add( "BaseVersionValue" );
+    attributeNames.Add( "CompareVersionValue" );
+    attributeNames.Add( "Gap" );
+    
+    return &attributeNames;
+  *]
+}
diff --git a/_Main/BL/Type_LocalCell_DemandComparison/StaticMethod_GetColumnXML.qbl b/_Main/BL/Type_LocalCell_DemandComparison/StaticMethod_GetColumnXML.qbl
new file mode 100644
index 0000000..308ed41
--- /dev/null
+++ b/_Main/BL/Type_LocalCell_DemandComparison/StaticMethod_GetColumnXML.qbl
@@ -0,0 +1,56 @@
+Quintiq file version 2.0
+#parent: #root
+StaticMethod GetColumnXML (
+  const constcontent LocalRows rows,
+  const LocalColumn column,
+  const Strings attributeNames,
+  String type
+) const as String
+{
+  TextBody:
+  [*
+    // rislai Jun-21-2024 (created)
+    // rislai Jun-20-2024 (created)
+    columnXML := "";
+    cells := selectsortedset( column, LocalCell.astype( LocalCell_DemandComparison ), cell,
+                                  exists( rows,Elements,element,element = cell.LocalRow()), cell.LocalRow().Index());
+    if( type = "data" ){
+      columnXML := "";
+      if( column.IsAttrbuteColumn() ){
+        columnXML := "<column><name>" + column.Name() + "</name><type>String</type>"; 
+      }else{
+        columnXML := "<column><name>" + column.Name() + "</name><type>Number</type>"; 
+      }
+      traverse ( cells, Elements, cell ) {
+        traverse( attributeNames ,Elements,e ){
+          cellXML := '<cell value="' + cell.GetAttributeByName( e ) + '"/>'
+          columnXML := columnXML + cellXML;
+        }
+      }
+      columnXML := columnXML + "</column>";
+    }
+    if( type = "attribute" ){
+      columnXML1 := "<column><name>Product ID</name><type>String</type>";
+      columnXML2 := "<column><name>Attribute</name><type>String</type>";
+      
+      traverse ( cells, Elements, cell ) {
+        flag := true;
+        traverse( attributeNames ,Elements,e ){
+          if( flag ){
+            cellXML := '<cell value="' + cell.LocalRow().Name() + '"/>'
+            columnXML1 := columnXML1 + cellXML;
+            flag := false;
+          }else{
+            cellXML := '<cell value="  "/>'
+            columnXML1 := columnXML1 + cellXML;
+          }
+          cellXML := '<cell value="' + e + '"/>'
+          columnXML2 := columnXML2 + cellXML;
+        }
+      }
+      columnXML := columnXML1 + "</column>" + columnXML2 + "</column>";
+    }
+     
+    return columnXML;
+  *]
+}
diff --git a/_Main/BL/Type_LocalCell_DemandComparison/_ROOT_Type_LocalCell_DemandComparison.qbl b/_Main/BL/Type_LocalCell_DemandComparison/_ROOT_Type_LocalCell_DemandComparison.qbl
new file mode 100644
index 0000000..d141f48
--- /dev/null
+++ b/_Main/BL/Type_LocalCell_DemandComparison/_ROOT_Type_LocalCell_DemandComparison.qbl
@@ -0,0 +1,9 @@
+Quintiq file version 2.0
+#root
+#parent: #DomainModel
+TypeSpecialization LocalCell_DemandComparison
+{
+  #keys: '2[412672.0.1087844722][412672.0.1087844717]'
+  Parent: LocalCell
+  StructuredName: 'LocalCell_DemandComparisons'
+}
diff --git a/_Main/BL/Type_LocalColumn/Attribute_IsAttrbuteColumn.qbl b/_Main/BL/Type_LocalColumn/Attribute_IsAttrbuteColumn.qbl
new file mode 100644
index 0000000..a41fb0a
--- /dev/null
+++ b/_Main/BL/Type_LocalColumn/Attribute_IsAttrbuteColumn.qbl
@@ -0,0 +1,7 @@
+Quintiq file version 2.0
+#parent: #root
+Attribute IsAttrbuteColumn
+{
+  #keys: '3[412672.0.1087874665][412672.0.1087874664][412672.0.1087874666]'
+  ValueType: Boolean
+}
diff --git a/_Main/BL/Type_LocalRow/Attribute_CustomName.qbl b/_Main/BL/Type_LocalRow/Attribute_CustomName.qbl
new file mode 100644
index 0000000..26849a4
--- /dev/null
+++ b/_Main/BL/Type_LocalRow/Attribute_CustomName.qbl
@@ -0,0 +1,7 @@
+Quintiq file version 2.0
+#parent: #root
+Attribute CustomName
+{
+  #keys: '3[412672.0.1094515780][412672.0.1094515779][412672.0.1094515781]'
+  ValueType: String
+}
diff --git a/_Main/BL/Type_LocalRow/Attribute_Name.qbl b/_Main/BL/Type_LocalRow/Attribute_Name.qbl
new file mode 100644
index 0000000..f53aa08
--- /dev/null
+++ b/_Main/BL/Type_LocalRow/Attribute_Name.qbl
@@ -0,0 +1,7 @@
+Quintiq file version 2.0
+#parent: #root
+Attribute Name
+{
+  #keys: '3[412672.0.1087844675][412672.0.1087844674][412672.0.1087844676]'
+  ValueType: String
+}
diff --git a/_Main/BL/Type_LocalRow/Function_CalcName.qbl b/_Main/BL/Type_LocalRow/Function_CalcName.qbl
new file mode 100644
index 0000000..c3cbb48
--- /dev/null
+++ b/_Main/BL/Type_LocalRow/Function_CalcName.qbl
@@ -0,0 +1,13 @@
+Quintiq file version 2.0
+#parent: #root
+Function CalcName
+{
+  TextBody:
+  [*
+    // rislai Jun-22-2024 (created)
+    
+    value := ifexpr( this.CustomName() = "",[String]this.Index(),this.CustomName() );
+    
+    this.Name( value );
+  *]
+}
diff --git a/_Main/BL/Type_LocalTable/Attribute_Name.qbl b/_Main/BL/Type_LocalTable/Attribute_Name.qbl
new file mode 100644
index 0000000..feeb6a2
--- /dev/null
+++ b/_Main/BL/Type_LocalTable/Attribute_Name.qbl
@@ -0,0 +1,7 @@
+Quintiq file version 2.0
+#parent: #root
+Attribute Name
+{
+  #keys: '3[412672.0.1094514009][412672.0.1094514008][412672.0.1094514010]'
+  ValueType: String
+}
diff --git a/_Main/BL/Type_Test/StaticMethod_Test.qbl b/_Main/BL/Type_Test/StaticMethod_Test.qbl
index df1ebb1..e2e3fe5 100644
--- a/_Main/BL/Type_Test/StaticMethod_Test.qbl
+++ b/_Main/BL/Type_Test/StaticMethod_Test.qbl
@@ -3,14 +3,42 @@
 StaticMethod Test (
   ScenarioManager scenarioManager,
   MacroPlan macroPlan,
-  Archive archive
+  Archive archive,
+  RecycleBin recycleBin
 )
 {
   TextBody:
   [*
     // rislai Jun-9-2024 (created)
-    element := "<column><name>Att</name><type>String</type>";
+    baseVersion := select( archive,ArchivePR,pr,true );
+    baseVersionFile := OSFile::Construct();
+    baseVersionFile.Open( baseVersion.FilePath(), "Read", false );
+    baseVersionBinaryData := baseVersionFile.ReadBinary();
+    baseVersionDataSource := GeneralExcelImportAndExportDataSource::Upload( recycleBin, baseVersionBinaryData, baseVersion.FilePath() );
+    baseVersionDataSource.ReadStructure();
     
-    error( element.LikeUserLocale( "Unit" ) );
+    baseVersionTables := selectset( baseVersionDataSource, GeneralExcelImportAndExportDataTable, tempGEIAEDT, true );
+    
+    baseVersionTable := baseVersionTables.Element( 0 );
+    
+    baseVersionRow := select( baseVersionTable, GeneralExcelImportAndExportDataRow, tempGEIAEDR, tempGEIAEDR.RowNr() = 999 );
+    
+    info( isnull( baseVersionRow ));
+    
+    
+    //testTree := NamedValueTree::Create();
+    //
+    //testTreeHandel := testTree.GetHandle( "test1" );
+    //testTreeHandel2 := testTree.GetHandle( "test2" );
+    //
+    //testTree.Root().AddChild( testTreeHandel,1 );
+    //
+    //info( testTree.Root().Child( testTreeHandel ).GetValueAsNumber() );
+    //try{
+    //  info( testTree.Root().Child( testTreeHandel2 ).GetValueAsNumber() ); 
+    //}onerror{
+    //  testTree.Root().AddChild( testTreeHandel,2 );
+    //}
+    //info( testTree.Root().Child( testTreeHandel ).GetValueAsNumber() );
   *]
 }
diff --git "a/_Main/UI/MacroPlannerWebApp/Component_ApplicationMacroPlanner/Component_ActionBarGroupScenarioComparisonViews\043859.def" "b/_Main/UI/MacroPlannerWebApp/Component_ApplicationMacroPlanner/Component_ActionBarGroupScenarioComparisonViews\043859.def"
new file mode 100644
index 0000000..062b204
--- /dev/null
+++ "b/_Main/UI/MacroPlannerWebApp/Component_ApplicationMacroPlanner/Component_ActionBarGroupScenarioComparisonViews\043859.def"
@@ -0,0 +1,18 @@
+Quintiq file version 2.0
+Component ActionBarGroupScenarioComparisonViews #extension
+{
+  Children:
+  [
+    Component ButtonScenarioComparisonDemandComparison
+    {
+      #keys: '[412672.0.1090347286]'
+      BaseType: 'WebButton'
+      Properties:
+      [
+        Image: 'EQUALS'
+        Label: '闇�姹傚姣�'
+        Taborder: 8
+      ]
+    }
+  ]
+}
diff --git a/_Main/UI/MacroPlannerWebApp/Component_ApplicationMacroPlanner/Component_ActionBarPageScenarioComparison.def b/_Main/UI/MacroPlannerWebApp/Component_ApplicationMacroPlanner/Component_ActionBarPageScenarioComparison.def
new file mode 100644
index 0000000..fb3b421
--- /dev/null
+++ b/_Main/UI/MacroPlannerWebApp/Component_ApplicationMacroPlanner/Component_ActionBarPageScenarioComparison.def
@@ -0,0 +1,8 @@
+Quintiq file version 2.0
+Component ActionBarPageScenarioComparison #extension
+{
+  Children:
+  [
+    #child: ActionBarGroupScenarioComparisonViews
+  ]
+}
diff --git a/_Main/UI/MacroPlannerWebApp/Component_ApplicationMacroPlanner/Response_MacroPlanner_ActionBarGroupDebug_ButtonTest_OnClick.def b/_Main/UI/MacroPlannerWebApp/Component_ApplicationMacroPlanner/Response_MacroPlanner_ActionBarGroupDebug_ButtonTest_OnClick.def
index 563d822..ea79d88 100644
--- a/_Main/UI/MacroPlannerWebApp/Component_ApplicationMacroPlanner/Response_MacroPlanner_ActionBarGroupDebug_ButtonTest_OnClick.def
+++ b/_Main/UI/MacroPlannerWebApp/Component_ApplicationMacroPlanner/Response_MacroPlanner_ActionBarGroupDebug_ButtonTest_OnClick.def
@@ -9,7 +9,9 @@
   {
     Body:
     [*
-      Test::Test( ScenarioManager,MacroPlan,Archive );
+      Test::Test( ScenarioManager,MacroPlan,Archive,RecycleBin );
+      
+      WebMessageBox::Success( "Success");
     *]
     GroupServerCalls: false
   }
diff --git a/_Main/UI/MacroPlannerWebApp/Component_ApplicationMacroPlanner/Response_MacroPlanner_ActionBarGroupScenarioComparisonViews_ButtonScenarioCo.def b/_Main/UI/MacroPlannerWebApp/Component_ApplicationMacroPlanner/Response_MacroPlanner_ActionBarGroupScenarioComparisonViews_ButtonScenarioCo.def
new file mode 100644
index 0000000..b8c7979
--- /dev/null
+++ b/_Main/UI/MacroPlannerWebApp/Component_ApplicationMacroPlanner/Response_MacroPlanner_ActionBarGroupScenarioComparisonViews_ButtonScenarioCo.def
@@ -0,0 +1,17 @@
+Quintiq file version 2.0
+#parent: ActionBarGroupScenarioComparisonViews/ButtonScenarioComparisonDemandComparison
+Response OnClick () id:Response_MacroPlanner_ActionBarGroupScenarioComparisonViews_ButtonScenarioComparisonDemandComparison_OnClick
+{
+  #keys: '[412672.0.1090347405]'
+  CanBindMultiple: false
+  DefinitionID: 'Responsedef_WebButton_OnClick'
+  QuillAction
+  {
+    Body:
+    [*
+      // Open view
+      ApplicationMacroPlanner.OpenView( 'DemandComparison', this );
+    *]
+    GroupServerCalls: false
+  }
+}
diff --git a/_Main/UI/MacroPlannerWebApp/Component_ApplicationMacroPlanner/_ROOT_Component_ApplicationMacroPlanner.def b/_Main/UI/MacroPlannerWebApp/Component_ApplicationMacroPlanner/_ROOT_Component_ApplicationMacroPlanner.def
index 86f5b1a..e01fbb6 100644
--- a/_Main/UI/MacroPlannerWebApp/Component_ApplicationMacroPlanner/_ROOT_Component_ApplicationMacroPlanner.def
+++ b/_Main/UI/MacroPlannerWebApp/Component_ApplicationMacroPlanner/_ROOT_Component_ApplicationMacroPlanner.def
@@ -20,6 +20,7 @@
         #child: abpAlgorithmPostProcessing
         #child: ActionBarPagePlan
         #child: ActionBarPageReport
+        #child: ActionBarPageScenarioComparison
       ]
     }
     Component dhBinaryDataPR id:dhBinaryDataPR_688
diff --git a/_Main/UI/MacroPlannerWebApp/Component_Form568/Response_pOperation_bDownload_OnClick.def b/_Main/UI/MacroPlannerWebApp/Component_Form568/Response_pOperation_bDownload_OnClick.def
index 24c257f..a78876c 100644
--- a/_Main/UI/MacroPlannerWebApp/Component_Form568/Response_pOperation_bDownload_OnClick.def
+++ b/_Main/UI/MacroPlannerWebApp/Component_Form568/Response_pOperation_bDownload_OnClick.def
@@ -19,7 +19,7 @@
   {
     Body:
     [*
-      binaryValue := ShiftPlan::Export( dhXMLDataListener.Data( ));
+      binaryValue := dhXMLDataListener.Data( ).Export();
       
       Application.Download( "鐝璁″垝_" + DateTime::Now().Format( "YM2D2H2mmss" ) + ".xlsx", binaryValue.AsBinaryData() );
       
diff --git a/_Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Component_MatrixEditor.def b/_Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Component_MatrixEditor.def
index dd916e8..e22590b 100644
--- a/_Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Component_MatrixEditor.def
+++ b/_Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Component_MatrixEditor.def
@@ -20,13 +20,13 @@
             DataType: 'LocalTable'
             Source: 'dhComparisonData'
             Taborder: 0
-            Transformation: 'LocalRow.LocalCell'
+            Transformation: 'LocalRow.LocalCell.astype(LocalCell_DemandComparison)'
           ]
         }
       ]
       Properties:
       [
-        Attributes: 'Value'
+        Attributes: 'BaseVersionValue;CompareVersionValue;BaseVersion;CompareVersion;Gap'
         Column: 'LocalColumn'
         Row: 'LocalRow'
         Taborder: 0
@@ -53,7 +53,7 @@
       ]
       Properties:
       [
-        Legend: 'Index'
+        Legend: 'Name'
         SortCriteria: 'Index'
         Taborder: 1
       ]
@@ -89,6 +89,7 @@
   ]
   Properties:
   [
+    AllowMultipleAttributes: true
     Columns: 'MatrixEditorColumns'
     ContextMenu: 'matrixeditorContextMenuDemandComparison'
     Rows: 'MatrixEditorRows'
diff --git a/_Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Component_PanelOperation.def b/_Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Component_PanelOperation.def
index c43c66e..eaac96e 100644
--- a/_Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Component_PanelOperation.def
+++ b/_Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Component_PanelOperation.def
@@ -6,7 +6,7 @@
   Children:
   [
     #child: PanelOperation11
-    Component ButtonOperation
+    Component ButtonCompare
     {
       #keys: '[412672.0.1085802121]'
       BaseType: 'WebButton'
@@ -16,6 +16,7 @@
         Taborder: 1
       ]
     }
+    #child: pOperation_715
   ]
   Properties:
   [
diff --git a/_Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Component_PanelOperation11.def b/_Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Component_PanelOperation11.def
index 0252f41..828d235 100644
--- a/_Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Component_PanelOperation11.def
+++ b/_Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Component_PanelOperation11.def
@@ -29,6 +29,8 @@
       ]
       Properties:
       [
+        DisplayField: 'Name'
+        Label: '瀵规瘮闇�姹傜増鏈細'
         Taborder: 2
       ]
     }
@@ -64,6 +66,8 @@
       ]
       Properties:
       [
+        DisplayField: 'Name'
+        Label: '鍩哄噯闇�姹傜増鏈細'
         Taborder: 0
       ]
     }
diff --git "a/_Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Component_pOperation\043715.def" "b/_Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Component_pOperation\043715.def"
new file mode 100644
index 0000000..b50844d
--- /dev/null
+++ "b/_Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Component_pOperation\043715.def"
@@ -0,0 +1,63 @@
+Quintiq file version 2.0
+Component pOperation id:pOperation_715
+{
+  #keys: '[412672.0.1092111928]'
+  BaseType: 'WebPanel'
+  Children:
+  [
+    Component bExport
+    {
+      #keys: '[412672.0.1092111929]'
+      BaseType: 'WebButton'
+      Properties:
+      [
+        Image: 'EXPORT1'
+        Label: '瀵煎嚭'
+        Taborder: 0
+      ]
+    }
+    Component bDownload
+    {
+      #keys: '[412672.0.1092111930]'
+      BaseType: 'WebButton'
+      Properties:
+      [
+        Image: 'DOWNLOAD'
+        Label: '涓嬭浇'
+        Taborder: 1
+      ]
+    }
+    Component dhXMLDataListener
+    {
+      #keys: '[412672.0.1092111931]'
+      BaseType: 'WebDataHolder'
+      Databinding: 'ExportXMLManager'
+      Children:
+      [
+        Component DataExtractor510
+        {
+          #keys: '[412672.0.1092111932]'
+          BaseType: 'WebDataExtractor'
+          Properties:
+          [
+            DataType: 'RecycleBin'
+            FixedFilter: 'object.Name() = "LocalTableXML"'
+            Source: 'RecycleBin'
+            Taborder: 0
+            Transformation: 'ExportXMLManager'
+          ]
+        }
+      ]
+      Properties:
+      [
+        Taborder: 2
+      ]
+    }
+  ]
+  Properties:
+  [
+    FixedSize: true
+    Orientation: 'horizontal'
+    Taborder: 2
+  ]
+}
diff --git a/_Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Response_PanelDemandComparison_dhComparisonData_OnDataChanged.def b/_Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Response_PanelDemandComparison_dhComparisonData_OnDataChanged.def
new file mode 100644
index 0000000..16bd708
--- /dev/null
+++ b/_Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Response_PanelDemandComparison_dhComparisonData_OnDataChanged.def
@@ -0,0 +1,16 @@
+Quintiq file version 2.0
+#parent: PanelDemandComparison/dhComparisonData
+Response OnDataChanged () id:Response_PanelDemandComparison_dhComparisonData_OnDataChanged
+{
+  #keys: '[412672.0.1093351461]'
+  CanBindMultiple: false
+  DefinitionID: 'Responsedef_WebComponent_OnDataChanged'
+  GroupServerCalls: true
+  QuillAction
+  {
+    Body:
+    [*
+      PanelDemandComparison.Title( this.Data().Name() );
+    *]
+  }
+}
diff --git "a/_Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Response_PanelOperation11_DropDownListBaseVersion_OnSelectionChanged\043168.def" "b/_Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Response_PanelOperation11_DropDownListBaseVersion_OnSelectionChanged\043168.def"
index b082604..a95fc67 100644
--- "a/_Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Response_PanelOperation11_DropDownListBaseVersion_OnSelectionChanged\043168.def"
+++ "b/_Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Response_PanelOperation11_DropDownListBaseVersion_OnSelectionChanged\043168.def"
@@ -13,6 +13,7 @@
     Body:
     [*
       dhBaseVersion.Data( selection );
+      this.Tooltip( selection.Name() );
     *]
   }
 }
diff --git a/_Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Response_PanelOperation11_DropDownListCompareVersion_OnSelectionChanged.def b/_Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Response_PanelOperation11_DropDownListCompareVersion_OnSelectionChanged.def
new file mode 100644
index 0000000..ba590f9
--- /dev/null
+++ b/_Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Response_PanelOperation11_DropDownListCompareVersion_OnSelectionChanged.def
@@ -0,0 +1,18 @@
+Quintiq file version 2.0
+#parent: PanelOperation11/DropDownListCompareVersion_85
+Response OnSelectionChanged (
+  ArchivePR selection
+) id:Response_PanelOperation11_DropDownListCompareVersion_OnSelectionChanged
+{
+  #keys: '[412672.0.1093350988]'
+  CanBindMultiple: false
+  DefinitionID: 'Responsedef_WebDropDownList_OnSelectionChanged'
+  GroupServerCalls: true
+  QuillAction
+  {
+    Body:
+    [*
+      this.Tooltip( selection.Name() );
+    *]
+  }
+}
diff --git a/_Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Response_PanelOperation_ButtonOperation_OnClick.def b/_Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Response_PanelOperation_ButtonCompare_OnClick.def
similarity index 76%
rename from _Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Response_PanelOperation_ButtonOperation_OnClick.def
rename to _Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Response_PanelOperation_ButtonCompare_OnClick.def
index e397283..a761ea1 100644
--- a/_Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Response_PanelOperation_ButtonOperation_OnClick.def
+++ b/_Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Response_PanelOperation_ButtonCompare_OnClick.def
@@ -1,6 +1,6 @@
 Quintiq file version 2.0
-#parent: PanelOperation/ButtonOperation
-Response OnClick () id:Response_PanelOperation_ButtonOperation_OnClick
+#parent: PanelOperation/ButtonCompare
+Response OnClick () id:Response_PanelOperation_ButtonCompare_OnClick
 {
   #keys: '[412672.0.1085802211]'
   CanBindMultiple: false
diff --git a/_Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Response_pOperation_715_bDownload_OnClick.def b/_Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Response_pOperation_715_bDownload_OnClick.def
new file mode 100644
index 0000000..1fd2a91
--- /dev/null
+++ b/_Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Response_pOperation_715_bDownload_OnClick.def
@@ -0,0 +1,30 @@
+Quintiq file version 2.0
+#parent: pOperation_715/bDownload
+Response OnClick () id:Response_pOperation_715_bDownload_OnClick
+{
+  #keys: '[412672.0.1092111926]'
+  CanBindMultiple: false
+  DefinitionID: 'Responsedef_WebButton_OnClick'
+  Precondition:
+  [*
+    flag := true;
+    feedback := "";
+    if( isnull( dhXMLDataListener.Data() )){
+      flag := false;
+      feedback := "褰撳墠鏃犱笅杞芥暟鎹紝鐐瑰嚮瀵煎嚭鍒涘缓涓嬭浇鏁版嵁銆�"
+    }
+    return flag;
+  *]
+  QuillAction
+  {
+    Body:
+    [*
+      binaryValue := dhXMLDataListener.Data( ).Export();
+      
+      Application.Download( "闇�姹傜増鏈姣擾" + DateTime::Now().Format( "YM2D2H2mmss" ) + ".xlsx", binaryValue.AsBinaryData() );
+      
+      dhXMLDataListener.Data( ).Delete();
+    *]
+    GroupServerCalls: false
+  }
+}
diff --git a/_Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Response_pOperation_715_bExport_OnClick.def b/_Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Response_pOperation_715_bExport_OnClick.def
new file mode 100644
index 0000000..02b5b31
--- /dev/null
+++ b/_Main/UI/MacroPlannerWebApp/Component_FormDemandComparison/Response_pOperation_715_bExport_OnClick.def
@@ -0,0 +1,18 @@
+Quintiq file version 2.0
+#parent: pOperation_715/bExport
+Response OnClick () id:Response_pOperation_715_bExport_OnClick
+{
+  #keys: '[412672.0.1092111927]'
+  CanBindMultiple: false
+  DefinitionID: 'Responsedef_WebButton_OnClick'
+  QuillAction
+  {
+    Body:
+    [*
+      rows := selectset( dhComparisonData.Data(),LocalRow,row,true );
+      columns := selectset( dhComparisonData.Data( ),LocalColumn,column,true );
+      LocalCell_DemandComparison::AsyncExport( RecycleBin, rows, columns );
+    *]
+    GroupServerCalls: false
+  }
+}
diff --git a/_Main/UI/MacroPlannerWebApp/Views/DemandComparison.vw b/_Main/UI/MacroPlannerWebApp/Views/DemandComparison.vw
new file mode 100644
index 0000000..3f13663
--- /dev/null
+++ b/_Main/UI/MacroPlannerWebApp/Views/DemandComparison.vw
@@ -0,0 +1,16 @@
+Quintiq file version 2.0
+{
+  viewcontents
+  {
+    page: ''
+    group: ''
+    index: 0
+    image: 'EQUALS'
+    description: ''
+  }
+  formatversion: 2
+  id: 'DemandComparison'
+  name: 'DemandComparison'
+  isglobal: false
+  isroot: true
+}

--
Gitblit v1.9.3