퇴근5분전



쿼리상에서의 피벗은 집계함수를 적용해야 하는데...

챠트를 구현하면서 나온 데이타를 피벗할필요없이 특정 컬럼을 기준으로 대상데이타를 가로축으로 변경하고자 할때 사용하면 됨.


이하 소스.

그리드뷰 4개를 놓고 왼쪽은 기본데이타 오른쪽은 피벗된 데이타.

Pivot(DataTable sourceTb, string sBaseColumnName, string sBaseHeaderColumnName, string RotColumnName)  : DataTable

소스 테이블, 컬럼이 될 데이타를 가진 컬럼명,   컬럼의 설명이 들어간 컬럼,  데이타컬럼

   피봇 전                                                            피봇 후





namespace PIVOT_TABLE
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            DataTable sourceTable = new DataTable();
            sourceTable.Columns.Add("YM_MAGAM");
            sourceTable.Columns.Add("CD_GMGS");
            sourceTable.Columns.Add("DS_GMGS");
            sourceTable.Columns.Add("AM_CURRENT1");

            sourceTable.Rows.Add(201006, "F100000", "유동비율(%)", 120.2);
            sourceTable.Rows.Add(201006, "F100100", "부채비율(%)", 367.6);
            sourceTable.Rows.Add(201006, "F100200", "차입금의존도(%)", 63.3);
            sourceTable.Rows.Add(201006, "F100300", "영업이익이자보상배율(배)", 0.1);
            sourceTable.Rows.Add(200912, "F100000", "유동비율(%)", 130.3);
            sourceTable.Rows.Add(200912, "F100100", "부채비율(%)", 207.0);
            sourceTable.Rows.Add(200912, "F100200", "차입금의존도(%)", 47.8);
            sourceTable.Rows.Add(200912, "F100300", "영업이익이자보상배율(배)", 2.4);
            sourceTable.Rows.Add(200812, "F100000", "유동비율(%)", 135.8);
            sourceTable.Rows.Add(200812, "F100100", "부채비율(%)", 107.2);
            sourceTable.Rows.Add(200812, "F100200", "차입금의존도(%)", 27.0);
            sourceTable.Rows.Add(200812, "F100300", "영업이익이자보상배율(배)", 2.7);

            dataGridView1.DataSource = sourceTable;


            dataGridView2.DataSource = Pivot(sourceTable, "CD_GMGS", "DS_GMGS", "AM_CURRENT1");


            DataTable sourceTable1 = new DataTable();
            sourceTable1.Columns.Add("YM_MAGAM");
            sourceTable1.Columns.Add("AM_JUMSU");


            sourceTable1.Rows.Add(200612,  null);
            sourceTable1.Rows.Add(200712,  null);
            sourceTable1.Rows.Add(200812,  null);
            sourceTable1.Rows.Add(200912,  27.5000);
            sourceTable1.Rows.Add(201006,  20.0000);

            dataGridView3.DataSource = sourceTable1;

            dataGridView4.DataSource = Pivot(sourceTable1, "YM_MAGAM", "YM_MAGAM", "AM_JUMSU");

        }

        /// <summary>
        /// 피벗 메서드.
        /// 소스 데이타를 특정 컬럼 기준으로 컬럼으로 확장 후 데이타를 확장컬럼에 넣어서 반환해줌.
        /// 추가 : 챠트에 쓰기 위해 NO를 추가해서 넘버링 함. ( 기준 BindingX 값으로 사용함 )
        /// 추가 : 나머지 컬럼은 모두 제자리.
        /// </summary>
        /// <param name="sourceTb"> 변환 될 데이타 테이블</param>
        /// <param name="sBaseColumnName"> 컬럼변경 데이타를 가진 컬럼명</param>
        /// <param name="sBaseHeaderColumnName"> 컬럼에 대한 헤더컬럼.</param>
        /// <param name="RotColumnName"> 옮겨질 데이타. </param>
        /// <returns></returns>
        DataTable Pivot(DataTable sourceTb, string sBaseColumnName, string sBaseHeaderColumnName, string RotColumnName)
        {
            DataTable dt = new DataTable();
            int sBaseColumnIndex = sourceTb.Columns.IndexOf(sBaseColumnName);
            int sBaseHeaderColumnIndex = sourceTb.Columns.IndexOf(sBaseHeaderColumnName);
            int sRotColumnIndex = sourceTb.Columns.IndexOf(RotColumnName);

            dt.Columns.Add("_NO");
            for (int colIndex = 0; colIndex < sourceTb.Columns.Count; colIndex++)
            {
                if (sBaseColumnIndex == colIndex || sRotColumnIndex == colIndex || sBaseHeaderColumnIndex == colIndex) continue;
                dt.Columns.Add(string.Format("_{0}", sourceTb.Columns[colIndex].ColumnName));
            }

            string ColName = string.Empty;

            foreach (DataRow sBaseColumnRow in sourceTb.Rows)
            {
                ColName = sBaseColumnRow[sBaseColumnIndex].ToString();
                if (!dt.Columns.Contains(string.Format("_{0}", ColName)))
                {
                    dt.Columns.Add(string.Format("_{0}", ColName));
                    if (sBaseHeaderColumnIndex >= 0)
                        dt.Columns[dt.Columns.Count - 1].Caption = sBaseColumnRow[sBaseHeaderColumnIndex].ToString();
                }
            }
            int offsetCol = sBaseHeaderColumnIndex == -1 ? 2 : 3;

            // Row 한번에 뛰어넘을 간격을 계산함.
            int step = dt.Columns.Count - (sourceTb.Columns.Count - offsetCol) - 1; // 1은 NO 컬럼 몫.

            if (step <= 0)
            {
                throw new Exception("RowIndex 계산증가값은 0이하가 될수 없습니다.");
            }

            List<object> values = new List<object>();
            for (int rowIndex = 0; rowIndex < sourceTb.Rows.Count; rowIndex += step)
            {
                values.Add(dt.Rows.Count + 1);
                for (int colIndex = 0; colIndex < sourceTb.Columns.Count; colIndex++)
                {
                    if (sBaseColumnIndex == colIndex || sRotColumnIndex == colIndex || sBaseHeaderColumnIndex == colIndex) continue;

                    values.Add(sourceTb.Rows[rowIndex][colIndex]); // 기존 컬럼 복사
                }

                for (int i = 0; i < step; i++) // 세로로 된 기준 컬럼데이타를 가로로 복사함.
                {
                    if (sourceTb.Rows.Count <= rowIndex + i) break;
                    values.Add(sourceTb.Rows[rowIndex + i][sRotColumnIndex]);
                }
                dt.Rows.Add(values.ToArray<object>());
                values.Clear();
            }
            return dt;
        }


    }
}