This page looks plain and unstyled because you're using a non-standard compliant browser. To see it in its best form, please visit upgrade to a browser that supports web standards. It's free and painless.

Marlon.ERP 會員登入 會員註冊

  ERP系統的資料庫中存放了各式各樣的企業資料,但是僅能透過系統提供的報表將這些資料以有用的資訊呈現,否則除非熟悉系統檔案的規格,不然連專業的IT人員也不見得可以重組這些資料變成有用的資訊,更別說是一般使用者了。資料庫中明明有那麼多的資料卻無法加以利用,於是各企業又陸續花大錢導入BI系統,但對於非「例行公事」的臨時性報表,或者是之後才產生的新需求,一般使用者還是很難從資料庫取得想要的資訊,相信這是很多企業在導入了ERPBI後心中永遠的痛。

   大家熟知的 Excel試算表軟體內含一個功能還算不錯的樞紐分析表,它分成列(緃軸)、欄(橫軸)、頁面及資料四個區域,例如在頁面區擺放幣別欄位,在列區擺放貨品類別及員工欄位,在欄區擺放銷售月份欄位,在資料區擺放銷售金額欄位並做加總 (或計數、平均、取最大最小、算標準差、變異值等各種統計方法),就成了業務員每種貨品(緃軸)各月份(橫軸)的銷售總額報表(一次只看一種幣別),只要雙擊統計值就會開啟新工作表顯示明細資料,也可從樞紐分析表產生圖表。這樣的功能是否令人心動呢?以Wanpie ERP的傳票分錄為例,每一個會計科目可以分別為借方及貸方從80種分析角度中挑選出數個做為傳票輸入的必要或非必要欄位(Wanpie ERP中稱為製票要件),配合Excel的樞紐分析功能就可以輕易地對不同的會計科目選用不同的分析角度產生各式各樣的統計報表,成為企業財務分析的利器。

  但是想做出樞紐分析表,首先必須從ERP中查詢資料複製到Excel中,然後去做樞紐分析的欄位設定,而且一旦資料異動了或者想查詢的條件範圍異動了,所有的動作就要重來一次,藉由專業人員撰寫Excel巨集指令或許可以減少部份設定工作,但如果ERP系統的支援不夠,光是資料可能都得交由IT人員直接下SQL去資料庫查詢。這時候需要一座橋樑完美地讓ERP資料與Excel樞紐分析表合而為一,才能讓一般使用者快速地交出老闆臨時交辦的統計表,來看看Wanpie是如何搭起這座橋的:

  • 資料查詢
Wanpie ERP原本就具有強大而友善的查詢介面,幾乎所有表單中看的到的欄位都可以下條件,條件值可以輸入單一值,數個值或區間值,也可以輸入登入者帳號、員工編號、部門、登入公司等系統變數,最重要的是任何日期欄位都可以依系統日期自動加減計算(例如前一個月的1日到月底),讓週期性的條件不必每次輸入,然後把不同欄位的條件組合預存成各種版本。
  • 樞紐分析欄位設定
沿用條件欄位的設定介面,讓使用者可以自選那些欄位要放置在樞紐分析表的那個區域,儲存成各種版本。另外還可以將同一群組的明細資料合併以群組來呈現,自行輸入資料欄位的計算公式,並在客戶的提議下加了一個貼心的小功能,從Excel樞紐分析表雙擊統計值展開明細後,還可進一步點擊超連結在Wanpie ERP開啟這筆明細的來源表單。  由於條件及樞紐分析欄位設定都可預存成各種版本,再透過排程就可以在固定時間把特定日期區間的統計分析表自動以 e-mail 發送給相關人員。有了這麼強大的工具,是否得開始擔心重要的企業資訊會不會輕易外流?Wanpie ERP還有資料查詢保密功能為企業最重要的資產做防護。

最近接到客戶回報一個例外狀況 :
System.InvalidOperationException: 作業無效,因為它會產生對 SetCurrentCellAddressCore 函式的可重新進入呼叫。

System.Windows.Forms.DataGridView.SetCurrentCellAddressCore(Int32 columnIndex, Int32 rowIndex, Boolean setAnchorCellAddress, Boolean validateCurrentCell, Boolean throughMouseClick)

System.Windows.Forms.DataGridView.set_CurrentCell(DataGridViewCell value)

System.Windows.Forms.DataGridView.OnBindingContextChanged(EventArgs e)

System.Windows.Forms.Control.CreateControl()

System.Windows.Forms.Control.WmShowWindow(Message& m)

System.Windows.Forms.Control.WndProc(Message& m)

System.Windows.Forms.DataGridView.WndProc(Message& m)

System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)

System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

原本以為是設定 DataGridView.CurrentCell = xxx => 引發事件 => 在處理函式中又重覆設定 DataGridView.CurrentCell 造成的, 於是全面搜尋 source code 找出有設定 CurrentCell 的程式碼卻沒有發現上述的情形, 經同事指出發生這種例外的一種狀況是 "以對話框顯示 DataGridView 供使用者編輯資料, 使用者在 DataGridView 某一種自行開發的 DataGridViewColumn 還是編輯模式下直接按"X"關閉對話框, 下次再顯示這個對話框前清除 DataGridView 繫結的舊資料" 時就會出現, 後來我又測出不管是何種型態的 DataGridViewColumn, 只要是在 DataGridView 還在編輯模式下關閉對話框也會發生, 於是寫了一個簡單的程式模擬這個狀況 :

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Data;
namespace WindowsApplication1
{
    static class Program
    {
        /// <summary>
        /// 應用程式的主要進入點。
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MainForm());
        }
    }
 
    class MainForm : Form
    {
        public MainForm()
        {
            //to display Exception
            textBox = new TextBox();
            textBox.Multiline = true;
            textBox.ReadOnly = true;
            textBox.ScrollBars = ScrollBars.Both;
            textBox.Dock = DockStyle.Fill;
            this.Controls.Add(textBox);
         }
 
        protected override void OnShown(EventArgs e)
        {
            base.OnShown(e);
            showdlg(); //ok
            showdlg(); //catch a Exception
         }
 
        TextBox textBox;
        DataGridViewDialog dlg;
 
        void showdlg()
        {
            if (dlg == null) //create a dialog with DataGridView
            {
                dlg = new DataGridViewDialog();
                dlg.Shown += new EventHandler(dlg_Shown);
                dlg.Disposed += new EventHandler(dlg_Disposed);
            }
            try { dlg.ClearData(); } catch (Exception exp) { appendExceptionMsg(exp); }
            dlg.ShowDialog();
        }
 
        void appendExceptionMsg(Exception exp)
        {
            textBox.AppendText(exp.GetType().FullName + ":");
            textBox.AppendText(exp.Message + "\r\n");
            if (exp.TargetSite != null)
                textBox.AppendText(exp.TargetSite.Name + "\r\n");
            textBox.AppendText(exp.StackTrace);
            if (exp.InnerException != null)
            {
                textBox.AppendText("\r\n\r\n");
                appendExceptionMsg(exp.InnerException);
            }
        }
 
        void dlg_Disposed(object sender, EventArgs e)
        {
            dlg = null;
        }
 
        void dlg_Shown(object sender, EventArgs e)
        {
            dlg.Close();
        }
    }
 
    class DataGridViewDialog : Form
    {
        public DataGridViewDialog()
        {
            dataGridView1 = new DataGridView();
            dataGridView1.Dock = DockStyle.Fill;
            dataGridView1.EditMode = DataGridViewEditMode.EditOnEnter; //let DataGridView in edit mode
            this.Controls.Add(dataGridView1);
            table = new DataTable();
            table.Columns.Add("C1", typeof(string));
            table.Columns.Add("C2", typeof(string));
            for (int i = 0; i < 2; i++)
                table.Rows.Add(new object[] { i });
            bs = new BindingSource();
            bs.DataSource = table;
            dataGridView1.DataSource = bs;
         }
 
        public void ClearData()
        {
            table.Rows.Clear();
        }
 
        //protected override void OnFormClosed(FormClosedEventArgs e)
        //{
        //    base.OnFormClosed(e);
        //    this.dataGridView1.CurrentCell = null;
        //}

        DataTable table;
        BindingSource bs;
        DataGridView dataGridView1;
    }
}

結果這次抓到的是 :

System.NullReferenceException:並未將物件參考設定為物件的執行個體
get_MouseOverEditingControl
   於 System.Windows.Forms.DataGridView.get_MouseOverEditingControl()
   於 System.Windows.Forms.DataGridView.EndEdit(DataGridViewDataErrorContexts context, DataGridViewValidateCellInternal validateCell, Boolean fireCellLeave, Boolean fireCellEnter, Boolean fireRowLeave, Boolean fireRowEnter, Boolean fireLeave, Boolean keepFocus, Boolean resetCurrentCell, Boolean resetAnchorCell)
   於 System.Windows.Forms.DataGridView.SetCurrentCellAddressCore(Int32 columnIndex, Int32 rowIndex, Boolean setAnchorCellAddress, Boolean validateCurrentCell, Boolean throughMouseClick)
   於 System.Windows.Forms.DataGridView.set_CurrentCell(DataGridViewCell value)
   於 System.Windows.Forms.DataGridView.OnClearingRows()
   於 System.Windows.Forms.DataGridViewRowCollection.ClearInternal(Boolean recreateNewRow)
   於 System.Windows.Forms.DataGridView.RefreshRows(Boolean scrollIntoView)
   於 System.Windows.Forms.DataGridView.DataGridViewDataConnection.ProcessListChanged(ListChangedEventArgs e)
   於 System.Windows.Forms.DataGridView.DataGridViewDataConnection.currencyManager_ListChanged(Object sender, ListChangedEventArgs e)
   於 System.Windows.Forms.CurrencyManager.OnListChanged(ListChangedEventArgs e)
   於 System.Windows.Forms.CurrencyManager.List_ListChanged(Object sender, ListChangedEventArgs e)
   於 System.Windows.Forms.BindingSource.OnListChanged(ListChangedEventArgs e)
   於 System.Windows.Forms.BindingSource.InnerList_ListChanged(Object sender, ListChangedEventArgs e)
   於 System.Data.DataView.OnListChanged(ListChangedEventArgs e)
   於 System.Data.DataView.IndexListChanged(Object sender, ListChangedEventArgs e)
   於 System.Data.DataView.IndexListChangedInternal(ListChangedEventArgs e)
   於 System.Data.DataViewListener.IndexListChanged(ListChangedEventArgs e)
   於 System.Data.Index.<OnListChanged>b__2(DataViewListener listener, ListChangedEventArgs args, Boolean arg2, Boolean arg3)
   於 System.Data.Listeners`1.Notify[T1,T2,T3](T1 arg1, T2 arg2, T3 arg3, Action`4 action)
   於 System.Data.Index.OnListChanged(ListChangedEventArgs e)
   於 System.Data.Index.FireResetEvent()
   於 System.Data.Index.Reset()
   於 System.Data.DataTable.ResetInternalIndexes(DataColumn column)
   於 System.Data.DataTable.Clear(Boolean clearAll)
   於 System.Data.DataRowCollection.Clear()
   於 WindowsApplication1.DataGridViewDialog.ClearData() 於 C:\Users\Marlon.Wu\AppData\Local\Temporary Projects\WindowsApplication1\Program.cs: 行 114
   於 WindowsApplication1.MainForm.showdlg() 於 C:\Users\Marlon.Wu\AppData\Local\Temporary Projects\WindowsApplication1\Program.cs: 行 56
    
關閉對話框前把 DataGridView.CurrentCell 設為 null 可以避免這種例外狀況

  ERP 存放了企業大量的敏感性資料, 如果缺乏完善的防護措施, 很容易就被員工一覽無遺, 甚至外洩商業機密危害公司的利益, 因此 WanpieErp 提供了各種層面的資料防護及稽查措施 :

[程式權限控管] : 使用者僅能從選單上看到並開啟被授權的程式
應用實例 : 會計人員才具有傳票輸入的程式權限

[功能權限控管] : 使用者執行個別程式後, 僅能執行該程式中被授權的功能項目, 如新增, 修改, 刪除, 作廢, 查詢, 資料匯出, 列印等各項功能, 授權範圍可選擇個人權限, 部門權限, 組織權限 (含下級單位) 或不設限, 個人權限可指定代理人, 表格式的明細資料在不具備資料匯出權限時無法透過作業系統的剪貼簿功能複製表格資料
應用實例 : 業務助理僅能新增訂單資料
     業務代表只能修改, 刪除, 作廢, 查詢個人及助理登打的訂單資料
        業務主管可查詢整個部門的訂單資料
        地區主管可查詢隸屬該地區所有部門的訂單資料  
        高階主管可查詢全公司的訂單資料
 
[欄位權限控管] : 針對個別程式中的個別欄位授權給特定人員, 具有權限的人才能查看及修改該欄位的資料
應用實例 : 進貨價格, 銷貨成本及員工薪資欄位只授權給相關人員

[資料權限控管] : 針對特定資料 (如客戶資料, 會計科目) 設定使用者可以使用及查詢的範圍
應用實例 : 讓不同的業務員負責不同區域的客戶, 無法取得非責任區的客戶名單及客戶訂單等相關表單

[欄位預設值+唯讀鎖定+必要輸入] : 個別程式的資料輸入欄位或查詢欄位均可設定預設值, 並鎖定唯讀狀態讓使用者無法更改, 讓使用者僅能輸入或查詢預設的欄位值, WanpieErp 的查詢欄位允許使用者自行挑選組合並預存成不同版本, 設為必要輸入即可確保查詢時包含該欄位的預設條件值。一個欄位的條件值可輸入多筆資料或多區間值或資料與區間值混合, 可設定為反向條件。預設值支援使用者變數(如使用者的登入帳號, 員工編號, 部門等)及日期時間變數 (依資料庫主機系統時間做指定的運算, 如目前主機系統時間的年/前一個月/當月最後一天, 我們稱之為走動式日期設定)
應用實例 : 讓使用者只能查詢限定日期區間內的資料, 或限定金額以內的資料

[使用記錄稽查] : 完整記錄使用者何時何地登入, 開啟那些程式, 查詢列印異動那些資料, 何時登出

  WanpieErp 基礎架構完成後最先開發的是投資理財及店面承租管理模組, 提供給前一版的舊客戶財經資訊與新竹貨運使用, 接著完成的是財務會計及固定資產模組, 其他模組正陸續開發中, 有的還在規格文件階段, 這時中華電視台找我們去做產品介紹, 當時正是舊版要汰換而新版又未完成的青黃不接時期, 最後還是決定硬著頭皮拿著新版的半成品去做展示, 測試客戶對 WanpieErp 的反應, 就算失敗也可換得無價的實戰經驗, 結果這次的初登場成功打動在座觀眾, 這段歷史可以參考 iThome 的 CIO Talk "華視40年老店翻新營運系統 用IT打好基礎創造新價值" 一文。隨著華視的上線時程, 我們在接下來的幾個月不僅陸續完成電子表單簽核及人力資源模組, 更重要的是經由使用者回饋的寶貴意見, 我們不斷地修正、增強各方面功能, 秉持好還要更好的精神改到客戶滿意為止, 這段歷練過程讓 WanpieErp 更上一層樓, 奠定日後足以徹底擺脫競爭對手糾纏的根基。

 (閱讀全文)

  很多客戶找不到合適的 ERP, 因為大多數的 ERP 要客戶去適合它, 我們多年來彙集了各行各業的需求, 以不同的思維打造出與眾不同的 ERP, 有些不明就裡的同業批評我們的系統沒有流程可言, 殊不知武功的最高境界正是無招勝有招, 在我們系統的千變萬化中, 每一步都是經過精心設計環環相扣而不是漫無目的亂無章法, 提供自主流程規劃取代特定流程才能讓高手得以盡情施展而不是處處受限, 不必再經由客製就可以量身訂做企業專屬的流程, 這正是 WanpieErp 能獲得一流企業青睞的魅力。 

 (閱讀全文)
1 2 3 4 5 6 7  下一篇»