[정보] IT정보&활용 2024. 11. 29. 18:21

엑셀로 IPA 분석하기, VBA 활용

반응형

IPA(Importance Performance Analysis) 분석이란 응답자가 지각하는 특정 요소에 대한 성과(만족도)와 중요도를 각각 X와 Y축으로 하는 2차원상의 평면위에 좌표로 각 요소를 표현하는 분석방법을 말합니다.

응답자가 인식하는 중요도와 다른 하나의 변수(만족도, 성과, 필요도 등)와 비교하는 것인데, 같은 질문에 대해 두가지 속성으로 물어보는 경우 사분면으로 그려서 시각적으로 보여줄 수 있어 유용합니다.

 

방법은 항목별 평균을 전체평균을 기준으로 그보다 높은가 낮은가를 비교하는 방식이라 구현이 그렇게 어려운 것은 아닙니다.

다만 그래프로 시각화하는 과정이 손이 많이 가는 바, VBA로 그래프를 만드는 과정을 자동화해 보았습니다.

IPA 분석 결과
IPA 분석_vba v2024-1130.xlsm
0.06MB

반응형
[정보] IT정보&활용 2024. 11. 6. 12:10

PDF 나누기(split)

반응형

PDF 나누기.html
0.01MB

 

PDF를 두개로 나누는 html입니다.

 

pdf-lib (MIT 라이선스): https://github.com/Hopding/pdf-lib
pdf.js (Apache 2.0 라이선스): https://github.com/mozilla/pdf.js
위 라이브러리를 사용하였으며, chatGPT 등의 도움을 받아 실습 삼아 만들어 보았습니다.

 

아래는 html 스크립트 입니다.

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>PDF 나누기 (Split)</title>

    <!-- pdf-lib 및 pdf.js 라이브러리 로드 -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf-lib/1.17.1/pdf-lib.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.10.377/pdf.min.js"></script>

    <style>
        body {
            font-family: Arial, sans-serif;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            background-color: #f3f4f6;
            margin: 0;
        }
        .container {
            width: 100%;
            max-width: 500px;
            padding: 20px;
            background: white;
            border-radius: 8px;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
        }
        h1 {
            font-size: 24px;
            color: #333;
            text-align: center;
        }
        p {
            font-size: 14px;
            color: #555;
            text-align: left;
        }
        input[type="file"] {
            width: 100%;
            padding: 10px;
            margin: 10px 0;
            font-size: 14px;
        }
        input[type="number"] {
            width: 50%;
            padding: 10px;
            margin: 10px 0;
            font-size: 14px;
        }
        #split-button {
            width: 100%;
            padding: 12px;
            background-color: #28a745;
            color: white;
            border: none;
            border-radius: 5px;
            font-size: 16px;
            cursor: pointer;
            margin-top: 10px;
        }
        #split-button:hover {
            background-color: #218838;
        }
        footer {
            text-align: left;
            font-size: 12px;
            color: #777;
            margin-top: 20px;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>PDF 나누기</h1>
        <p>PDF를 두 개의 파일로 나눌 수 있습니다.</p>
        <p>1. "파일 선택" 버튼을 눌러 나눌 PDF 파일을 선택하세요.</p>
        <input type="file" id="file-input" accept="application/pdf" />

        <p>2. 나눌 페이지 번호를 입력하세요. <br>
             &nbsp;&nbsp;&nbsp;&nbsp;(예: 3을 입력하면 1-3페이지와 4-마지막 페이지로 나뉩니다.)</p>
        <input type="number" id="split-page" min="1" />

        <p>3. "PDF 나누기" 버튼을 누르세요.</p>
        <button id="split-button">PDF 나누기</button>

        <footer>
            <p><strong>사용된 라이브러리</strong></p>
            <ul>
                <li>pdf-lib (MIT 라이선스): <a href="https://github.com/Hopding/pdf-lib">https://github.com/Hopding/pdf-lib</a></li>
                <li>pdf.js (Apache 2.0 라이선스): <a href="https://github.com/mozilla/pdf.js">https://github.com/mozilla/pdf.js</a></li>
            </ul>
        </footer>
    </div>

<script>
    const fileInput = document.getElementById('file-input');
    const splitPage = document.getElementById('split-page');
    const splitButton = document.getElementById('split-button');

    splitButton.addEventListener('click', async () => {
        if (!fileInput.files[0]) {
            alert('PDF 파일을 선택해주세요.');
            return;
        }

        const pageNumber = parseInt(splitPage.value);
        if (isNaN(pageNumber) || pageNumber < 1) {
            alert('유효한 페이지 번호를 입력해주세요.');
            return;
        }

        const file = fileInput.files[0];
        const arrayBuffer = await file.arrayBuffer();
        const pdfDoc = await PDFLib.PDFDocument.load(arrayBuffer);

        if (pageNumber >= pdfDoc.getPageCount()) {
            alert('입력한 페이지 번호가 PDF의 총 페이지 수보다 크거나 같습니다.');
            return;
        }

        // 첫 번째 PDF 생성 (1부터 pageNumber까지)
        const firstPdf = await PDFLib.PDFDocument.create();
        const firstPages = await firstPdf.copyPages(pdfDoc, Array.from({length: pageNumber}, (_, i) => i));
        firstPages.forEach(page => firstPdf.addPage(page));

        // 두 번째 PDF 생성 (pageNumber+1부터 끝까지)
        const secondPdf = await PDFLib.PDFDocument.create();
        const secondPages = await secondPdf.copyPages(pdfDoc, Array.from({length: pdfDoc.getPageCount() - pageNumber}, (_, i) => i + pageNumber));
        secondPages.forEach(page => secondPdf.addPage(page));

        // PDF 저장 및 다운로드
        const firstPdfBytes = await firstPdf.save();
        const secondPdfBytes = await secondPdf.save();

        downloadPdf(firstPdfBytes, 'split_first.pdf');
        downloadPdf(secondPdfBytes, 'split_second.pdf');
    });

    function downloadPdf(pdfBytes, fileName) {
        const blob = new Blob([pdfBytes], { type: 'application/pdf' });
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = fileName;
        a.click();
        URL.revokeObjectURL(url);
    }
</script>

</body>
</html>

반응형
[정보] IT정보&활용 2024. 11. 1. 13:10

PDF 파일 합치기(수정)

반응형
더보기

디자인을 가미하기 전 순수 스크립트만 담겨있는 초기 버전입니다.

소스 검토용으로 남겨놓습니다.

PDF 합치기.html
0.00MB

PDF 합치기 v2.html
0.01MB

 

위 파일을 자신의 컴퓨터로 다운 받아서 그냥 실행하시면 됩니다.

 

 

 

pdf-lib (MIT 라이선스): https://github.com/Hopding/pdf-lib
pdf.js (Apache 2.0 라이선스): https://github.com/mozilla/pdf.js

 

위 두 개의 라이브러리를 사용하였으며, chatGPT 등의 도움을 받아 실습 삼아 만들어 보았습니다.

 

아래는 html 스크립트입니다.

---------------------------------------------

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>PDF 합치기 (Merge)</title>

    <!-- pdf-lib 및 pdf.js 라이브러리 로드 -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf-lib/1.17.1/pdf-lib.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.10.377/pdf.min.js"></script>

    <!-- 스타일링 -->
    <style>
        body {
            font-family: Arial, sans-serif;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            background-color: #f3f4f6;
            margin: 0;
        }
        .container {
            width: 100%;
            max-width: 500px;
            padding: 20px;
            background: white;
            border-radius: 8px;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
        }
        h1 {
            font-size: 24px;
            color: #333;
            text-align: center;
        }
        p {
            font-size: 14px;
            color: #555;
            text-align: left;
        }
        input[type="file"] {
            width: 100%;
            padding: 10px;
            margin: 10px 0;
            font-size: 14px;
        }
        #file-list {
            list-style: none;
            padding: 0;
            margin: 10px 0;
        }
        #file-list li {
            padding: 10px;
            border: 1px solid #ddd;
            border-radius: 5px;
            margin: 5px 0;
            display: flex;
            justify-content: space-between;
            align-items: center;
            background-color: #f9f9f9;
        }
        .move-buttons button {
            padding: 5px;
            margin: 0 2px;
            background: #4a90e2;
            color: white;
            border: none;
            border-radius: 3px;
            cursor: pointer;
            font-size: 12px;
        }
        .move-buttons button:hover {
            background: #357ABD;
        }
        #merge-button {
            width: 100%;
            padding: 12px;
            background-color: #28a745;
            color: white;
            border: none;
            border-radius: 5px;
            font-size: 16px;
            cursor: pointer;
            margin-top: 10px;
        }
        #merge-button:hover {
            background-color: #218838;
        }
        footer {
            text-align: left;
            font-size: 12px;
            color: #777;
            margin-top: 20px;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>PDF 합치기</h1>
        <p>여러 개의 PDF를 하나로 합칠 수 있습니다.</p>
        <p>1. "파일 선택" 버튼을 눌러 합칠 파일을 선택하세요.</p>
        <input type="file" id="file-input" multiple accept="application/pdf" />

        <p>2. 아래 목록에서 ↑↓를 눌러 순서를 조정하세요.</p>
        <ul id="file-list"></ul>

        <p>3. 순서를 확인한 후 "PDF 합치기" 버튼을 누르세요.</p>
        <button id="merge-button">PDF 합치기</button>

        <footer>
            <p><strong>사용된 라이브러리</strong></p>
            <ul>
                <li>pdf-lib (MIT 라이선스): <a href="https://github.com/Hopding/pdf-lib">https://github.com/Hopding/pdf-lib</a></li>
                <li>pdf.js (Apache 2.0 라이선스): <a href="https://github.com/mozilla/pdf.js">https://github.com/mozilla/pdf.js</a></li>
            </ul>
        </footer>
    </div>

<script>
    const fileInput = document.getElementById('file-input');
    const fileList = document.getElementById('file-list');

    fileInput.addEventListener('change', () => {
        fileList.innerHTML = '';
        Array.from(fileInput.files).forEach((file, index) => {
            const li = document.createElement('li');
            li.textContent = file.name;
            li.dataset.index = index;

            // 이동 버튼 추가
            const moveButtons = document.createElement('div');
            moveButtons.classList.add('move-buttons');

            const upButton = document.createElement('button');
            upButton.textContent = '↑';
            upButton.addEventListener('click', () => moveItem(li, -1));

            const downButton = document.createElement('button');
            downButton.textContent = '↓';
            downButton.addEventListener('click', () => moveItem(li, 1));

            // 삭제 버튼 추가
            const deleteButton = document.createElement('button');
            deleteButton.textContent = '삭제';
            deleteButton.style.background = '#dc3545';
            deleteButton.style.marginLeft = '5px';
            deleteButton.addEventListener('click', () => li.remove());

            moveButtons.appendChild(upButton);
            moveButtons.appendChild(downButton);
            moveButtons.appendChild(deleteButton);
            li.appendChild(moveButtons);

            fileList.appendChild(li);
        });
    });

    function moveItem(item, direction) {
        const sibling = (direction === -1) ? item.previousElementSibling : item.nextElementSibling;
        if (sibling) {
            fileList.insertBefore(item, direction === -1 ? sibling : sibling.nextElementSibling);
        }
    }

    document.getElementById('merge-button').addEventListener('click', async () => {
        const files = Array.from(fileList.children).map(li => fileInput.files[li.dataset.index]);
        const mergedPdf = await PDFLib.PDFDocument.create();

        for (let file of files) {
            const arrayBuffer = await file.arrayBuffer();
            const pdfDoc = await PDFLib.PDFDocument.load(arrayBuffer);
            const pages = await mergedPdf.copyPages(pdfDoc, pdfDoc.getPageIndices());
            pages.forEach(page => mergedPdf.addPage(page));
        }

        const pdfBytes = await mergedPdf.save();
        const blob = new Blob([pdfBytes], { type: 'application/pdf' });
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = 'merged.pdf';
        a.click();
        URL.revokeObjectURL(url);
    });
</script>

</body>
</html>

반응형