ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Javascript] Table Cell Merge(테이블 셀 병합) - 중복값 처리
    나는야 개발자/Javascript 2022. 4. 4. 17:26

    오늘은 내가 프로젝트를 진행하면서 표와 관련되어 큰 필요성을 느꼈던 한 가지를 정리하려고 한다.

    의외로 많은 분들이 공감하는 부분중 하나일테니 두고두고 써먹자 !!

     

    (나도 두고두고 써먹기)

     

    중요도 : ★★★☆☆

     

    바로바로 ~~

    TABLE CELL MERGE !! a.k.a 중복값 병합

     

    좋은 plugin을 사용한다면 큰 무리없을 수도 있으나,

    내가 하나부터 열까지 주먹구구식으로 개발을 해야한다면 그야말로 큰 어려움이 아닐수가 없다 ㅜㅜ

     

    * 특히!! 띄엄띄엄 위치해 있는 반복된 값들에 대한 처리는 더더욱 어려울 것이다.

     

    바로 시작해보자...


    우선 test용 코드를 작성해보자 !!

     

    [작성 예시]

    <!doctype html>
    <html>
    <head>
        <script src="https://code.jquery.com/jquery-latest.min.js"></script>
        <style>
            table{
                border-collapse: collapse;
                border: 1px solid black;
            }
            table th, table td{
                border: 1px solid black;
                text-align: center;
                padding: 15px 30px;
            }
        </style>
    </head>
    <div>
        <table>
            <thead>
                <tr>
                    <th>이름</th>
                    <th>학번</th>
                    <th>과목</th>
                    <th>점수</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>권영진</td>
                    <td>20220404</td>
                    <td>사회</td>
                    <td>98</td>
                </tr>
                <tr>
                    <td>권영진</td>
                    <td>20220404</td>
                    <td>국어</td>
                    <td>100</td>
                </tr>
                <tr>
                    <td>궈녕진</td>
                    <td>20220404</td>
                    <td>물리</td>
                    <td>92</td>
                </tr>
                <tr>
                    <td>거녕진</td>
                    <td>20220404</td>
                    <td>영어</td>
                    <td>92</td>
                </tr>
                <tr>
                    <td>거녕진</td>
                    <td>20220404</td>
                    <td>영어</td>
                    <td>92</td>
                </tr>
                <tr>
                    <td>궈녕진</td>
                    <td>20220404</td>
                    <td>수학</td>
                    <td>96</td>
                </tr>
                <tr>
                    <td>궈녕진</td>
                    <td>20220404</td>
                    <td>화학</td>
                    <td>96</td>
                </tr>
            </tbody>
        </table>
    </div>
    <script>
        // 테이블을 병합하는 FUNCTION
        function mergeCell(idx){
            let tr_all = document.querySelectorAll('tbody > tr');
    
            let compare_text = null,
                select_text  = null;
    
            let all_tr_list    = [],
                current_tr_list = [];
    
            tr_all.forEach((tr)=>{
                let tr_idx = tr.rowIndex;
    
                if(compare_text == null){
                    current_tr_list.push(tr);
                    compare_text = $(tr).find('td').eq(idx).text();
                }else{
                    select_text = $(tr).find('td').eq(idx).text();
                    if(select_text == compare_text){
                        current_tr_list.push(tr);
                    }else{
                        all_tr_list.push(current_tr_list);
    
                        current_tr_list = [tr];
                        compare_text = select_text;
                    }
                }
    
                // 전체 tr의 길이와 선택된 tr의 index가 일치할 경우 (끝)
                if(tr_idx === tr_all.length){
                    all_tr_list.push(current_tr_list);
    
                    all_tr_list.forEach((current_tr_list)=>{
                        if(current_tr_list.length > 1){
                            current_tr_list.forEach((current_tr,current_tr_idx)=>{
                                if(current_tr_idx == 0)
                                        $(current_tr).find('td').eq(idx).prop('rowSpan', current_tr_list.length);
                                    else
                                        $(current_tr).find('td').eq(idx).hide();
                            })
                        }
                    })
                }
            })
        }
    </script>
    </html>

    작성 코드를 실행시켜보자 !!

     

    [결과 화면]


    이를 조금더 편리(?)하게 사용하려면,

    받는 Index를 List형태로 하여 처음부터 반복적으로 Cell Merge가 발생하도록 하면 되겠다.

     

    [작성 예시]

    <!doctype html>
    <html>
    <head>
        <script src="https://code.jquery.com/jquery-latest.min.js"></script>
        <style>
            table{
                border-collapse: collapse;
                border: 1px solid black;
            }
            table th, table td{
                border: 1px solid black;
                text-align: center;
                padding: 15px 30px;
            }
        </style>
    </head>
    <div>
        <table>
            <thead>
                <tr>
                    <th>이름</th>
                    <th>학번</th>
                    <th>과목</th>
                    <th>점수</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>권영진</td>
                    <td>20220404</td>
                    <td>사회</td>
                    <td>98</td>
                </tr>
                <tr>
                    <td>권영진</td>
                    <td>20220404</td>
                    <td>국어</td>
                    <td>100</td>
                </tr>
                <tr>
                    <td>궈녕진</td>
                    <td>20220404</td>
                    <td>물리</td>
                    <td>92</td>
                </tr>
                <tr>
                    <td>거녕진</td>
                    <td>20220404</td>
                    <td>영어</td>
                    <td>92</td>
                </tr>
                <tr>
                    <td>거녕진</td>
                    <td>20220404</td>
                    <td>영어</td>
                    <td>92</td>
                </tr>
                <tr>
                    <td>궈녕진</td>
                    <td>20220404</td>
                    <td>수학</td>
                    <td>96</td>
                </tr>
                <tr>
                    <td>궈녕진</td>
                    <td>20220404</td>
                    <td>화학</td>
                    <td>96</td>
                </tr>
            </tbody>
        </table>
    </div>
    <script>
        // 테이블을 병합하는 FUNCTION
        function mergeCell(idxList){
            let tr_all = document.querySelectorAll('tbody > tr');
    
            let compare_text = null,
                select_text  = null;
    
            let all_tr_list    = [],
                current_tr_list = [];
    
            idxList.forEach((idx)=>{
                tr_all.forEach((tr)=>{
                    let tr_idx = tr.rowIndex;
    
                    if(compare_text == null){
                        current_tr_list.push(tr);
                        compare_text = $(tr).find('td').eq(idx).text();
                    }else{
                        select_text = $(tr).find('td').eq(idx).text();
                        if(select_text == compare_text){
                            current_tr_list.push(tr);
                        }else{
                            all_tr_list.push(current_tr_list);
    
                            current_tr_list = [tr];
                            compare_text = select_text;
                        }
                    }
    
                    // 전체 tr의 길이와 선택된 tr의 index가 일치할 경우 (끝)
                    if(tr_idx === tr_all.length){
                        all_tr_list.push(current_tr_list);
    
                        all_tr_list.forEach((current_tr_list)=>{
                            if(current_tr_list.length > 1){
                                current_tr_list.forEach((current_tr,current_tr_idx)=>{
                                    if(current_tr_idx == 0)
                                            $(current_tr).find('td').eq(idx).prop('rowSpan', current_tr_list.length);
                                        else
                                            $(current_tr).find('td').eq(idx).hide();
                                })
                            }
                        })
                    }
                })
            })
        }
    </script>
    </html>

    실행 시켜보자

     

    [결과 화면]


    이렇게 두가지 방식(?)에 대해 작성하고 테스트를 진행해 보았다.

    해당 함수를 사용할 때에는 기본적으로 merge할 data는 sort를 하여 가져오는 것으로, merge 시킬 준비를 해주는것이 좋다 !!

     

     

    -- 참조를 하였다면 출처를 밝혀주시고, 사용 시 댓글에 감사 인사 달아주시면 큰 힘이 됩니다 !!

    -- 모두가 한 단계 더 성장 할 수 있기를 바랍니다.


    * thead의 tr의 수가 늘어나면 늘어난 수 만큼 tbody의 tr이 rowspan되지 않는 문제가 있어 아래와 같이 코드를 수정하였습니다. 참고 바랍니다 !

     

    <!doctype html>
    <html>
    <head>
        <script src="https://code.jquery.com/jquery-latest.min.js"></script>
        <style>
            table{
                border-collapse: collapse;
                border: 1px solid black;
            }
            table th, table td{
                border: 1px solid black;
                text-align: center;
                padding: 15px 30px;
            }
        </style>
    </head>
    <div>
        <table id="target">
            <thead>
                <tr>
                    <th>이름</th>
                    <th>학번</th>
                    <th>과목</th>
                    <th>점수</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>권영진</td>
                    <td>20220404</td>
                    <td>사회</td>
                    <td>98</td>
                </tr>
                <tr>
                    <td>권영진</td>
                    <td>20220404</td>
                    <td>국어</td>
                    <td>100</td>
                </tr>
                <tr>
                    <td>궈녕진</td>
                    <td>20220404</td>
                    <td>물리</td>
                    <td>92</td>
                </tr>
                <tr>
                    <td>거녕진</td>
                    <td>20220404</td>
                    <td>영어</td>
                    <td>92</td>
                </tr>
                <tr>
                    <td>거녕진</td>
                    <td>20220404</td>
                    <td>영어</td>
                    <td>92</td>
                </tr>
                <tr>
                    <td>궈녕진</td>
                    <td>20220404</td>
                    <td>수학</td>
                    <td>96</td>
                </tr>
                <tr>
                    <td>궈녕진</td>
                    <td>20220404</td>
                    <td>화학</td>
                    <td>96</td>
                </tr>
            </tbody>
        </table>
    
        <table id="target2">
            <thead>
                <tr>
                    <th>이름</th>
                    <th>학번</th>
                    <th>과목</th>
                    <th>점수</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>권영진</td>
                    <td>20220404</td>
                    <td>사회</td>
                    <td>98</td>
                </tr>
                <tr>
                    <td>권영진</td>
                    <td>20220404</td>
                    <td>국어</td>
                    <td>100</td>
                </tr>
                <tr>
                    <td>궈녕진</td>
                    <td>20220404</td>
                    <td>수학</td>
                    <td>96</td>
                </tr>
                <tr>
                    <td>궈녕진</td>
                    <td>20220404</td>
                    <td>화학</td>
                    <td>96</td>
                </tr>
            </tbody>
        </table>
    </div>
    <script>
        // 테이블을 병합하는 FUNCTION
        function mergeCell(tableId, idxList){
            let tr_all = document.getElementById(tableId).querySelectorAll('tbody > tr'),
                tr_last_index = tr_all[tr_all.length - 1].rowIndex;
    
            let compare_text = null,
                select_text  = null;
    
            let all_tr_list    = [],
                current_tr_list = [];
    
            idxList.forEach((idx)=>{
                tr_all.forEach((tr)=>{
                    let tr_idx = tr.rowIndex;
    
                    if(compare_text == null){
                        current_tr_list.push(tr);
                        compare_text = $(tr).find('td').eq(idx).text();
                    }else{
                        select_text = $(tr).find('td').eq(idx).text();
                        if(select_text == compare_text){
                            current_tr_list.push(tr);
                        }else{
                            all_tr_list.push(current_tr_list);
    
                            current_tr_list = [tr];
                            compare_text = select_text;
                        }
                    }
    
                    // 전체 tr의 길이와 선택된 tr의 index가 일치할 경우 (끝)
                    if(tr_idx === tr_last_index){
                        all_tr_list.push(current_tr_list);
    
                        all_tr_list.forEach((current_tr_list)=>{
                            if(current_tr_list.length > 1){
                                current_tr_list.forEach((current_tr,current_tr_idx)=>{
                                    if(current_tr_idx == 0)
                                            $(current_tr).find('td').eq(idx).prop('rowSpan', current_tr_list.length);
                                        else
                                            $(current_tr).find('td').eq(idx).hide();
                                })
                            }
                        })
                    }
                })
            })
        }
    </script>
    </html>

     

    감사합니다 !!

    '나는야 개발자 > Javascript' 카테고리의 다른 글

    [Javascript/기초] 변수 선언(const/var/let)  (0) 2022.03.08

    댓글

Designed by Tistory.