İlkokul Gelişim Raporunu Arkalı Önlü Kolayca Çıktı Alma

Aslında konuyu kod.pardus.org.tr sitesine yükleyecektim ama sayfa hata verdi. Buraya yükleyeyim, sonra güncellerim dedim ben de.

Ana sınıfı ve 1. sınıflarda artık karne yok. Sayfalar dolusu gelişim raporu var. Rapor da sağolsun tek dosya iniyor ve kağıtlara çift yönlü yazdırmak istediğinizde, öğrencinin raporu 5 sayfaysa arkasına diğer öğrencinin ilk sayfası geldiğinden, yazdırırken uzun uzun öğrenci öğrenci uğraşmak gerekiyor. Ya da tamamını tek taraflı bastırıp tonla kağıt israf etmek gerekiyor.

Üstelik liste aynı zamanda sınıf sıralı da değil, karışık. Bir de sınıf sınıf ayırmak gerekiyor.

Bunu çözmek için oturup chatcpt yardımıyla python kodu yazdım.

Tüm listeyi kişi kişi ayırıp, onu da sınıf sınıf gruplayıp, tek sayfa olanların sonuna birer boş sayfa ekleyip, tüm listeyi sınıf sırasına göre tekrar birleştirip çıktıya hazır tek dosya haline getiriyor.

Hazırladığım dosyaları buradan da paylaşıyorum. Konu çok dağılmasın diye önce tarifi verip, altına da uzun uzun komutları vereceğim.

1- Bir klasör açıp çalışmanızı tavsiye ederim. Klasörün içine setup.sh, venv.sh ve karne.py adlı üç dosya oluşturun. Aşağıda vereceğim kodları o dosyaların içine yapıştırın.

2- Üzerinde çalışacağınız Gelişim Raporu dosyasını bu klasörün içine alın ve dosya adını tam_dosya.pdf olarak değiştirin.

3- chmod +x setup.sh; ./setup.sh komutunu çalıştırın. Gerekli paket kurulumları yapacak.

4- chmod +x venv.sh; ./venv.sh komutunu çalıştırın. Klasör içinde sanal ortam oluşturup, ilgili paketi onun içinde kurup sonra da karne.py adlı dosyayı çalıştırarak sizin dosyanızı düzenleyecek ve birlesik_dosya.pdf adıyla size çıktıya hazır halini verecek.

(Chatcpt bazı komutların bilgisayarın ayarlarını değiştirebileceği sebebiyle, bilgisayara kurulması yerine sanal ortama kurulmasını tavsiye etti. İşlem bittikten sonra 4. maddedeki komutla oluşturulan venv adlı klasörü silebilirsiniz.)

Şimdi de oluşturduğumuz dosyaların içine konulacak komutları paylaşıyorum.

setup.sh adlı dosyanın içine şu komutları kopyalayıp yapıştırın:

#!/bin/bash

set -e

echo "Sistem güncelleniyor..."
sudo apt update

# Python3 kontrolü ve kurulumu
if ! command -v python3 &> /dev/null
then
    echo "Python3 bulunamadı. Yükleniyor..."
    sudo apt install -y python3
else
    echo "Python3 zaten yüklü."
fi

# pip3 kontrolü ve kurulumu
if ! command -v pip3 &> /dev/null
then
    echo "pip3 bulunamadı. Yükleniyor..."
    sudo apt install -y python3-pip
else
    echo "pip3 zaten yüklü."
fi

echo "Kurulum tamamlandı. Gerekli paketler venv içinde kurulacak."

venv.sh adlı dosyanın içine şu komutları kopyalayıp yapıştırın:

#!/bin/bash

set -e

# Sanal ortam için gerekli paket var mı, yoksa yükle
if ! dpkg -s python3-venv &> /dev/null; then
    echo "python3-venv paketi eksik. Yükleniyor..."
    sudo apt update
    sudo apt install -y python3-venv
else
    echo "python3-venv zaten kurulu."
fi

# Sanal ortam klasörü
VENV_DIR="venv"

# Sanal ortam yoksa oluştur
if [ ! -d "$VENV_DIR" ]; then
    echo "Sanal ortam oluşturuluyor..."
    python3 -m venv "$VENV_DIR"
else
    echo "Sanal ortam zaten mevcut."
fi

# Sanal ortamı aktif et
echo "Sanal ortam aktif ediliyor..."
source "$VENV_DIR/bin/activate"

# pip güncelle
echo "pip güncelleniyor..."
pip install --upgrade pip

# Gerekli Python paketlerini kur
echo "pypdf paketi kuruluyor..."
pip install pypdf

# karne.py çalıştır
echo "karne.py dosyası çalıştırılıyor..."
python karne.py

# (İsterseniz işlem sonunda ortamdan çıkabilirsiniz)
# deactivate

karne.py adlı dosyaya şu komutları kopyalayıp yapıştırın:

from pypdf import PdfReader, PdfWriter, PageObject
import os
import re
from collections import defaultdict

def get_individual_ranges(pdf_path):
    reader = PdfReader(pdf_path)
    total = len(reader.pages)
    ranges = []

    i = 0
    while i < total:
        text = reader.pages[i].extract_text() or ""
        match = re.search(r"1\s*/\s*(\d+)", text)
        if match:
            count = int(match.group(1))
            start = i
            end = i + count - 1
            if end < total:
                ranges.append((start, end))
                i = end + 1
            else:
                print(f"UYARI: {start+1}. sayfada başlayan kişi için yeterli sayfa yok.")
                break
        else:
            i += 1
    return ranges

def extract_sinif_sube_from_footer(text):
    """
    Metnin son 5 satırından sınıf ve şube bilgisini arar.
    Örnek: "Ana Sınıfı/B Şubesi" veya "1. Sınıf/A Şubesi" gibi.
    Bulamazsa ("Bilinmeyen Sınıf", "X") döner.
    """
    lines = text.splitlines()
    footer_lines = lines[-5:] if len(lines) >= 5 else lines
    footer_text = " ".join(footer_lines)

    # Ana Sınıfı veya 1. Sınıf gibi sınıf + / veya boşluk + şube + Şubesi
    match = re.search(r"(Ana Sınıfı|\d+\. Sınıf)[\s]*[/\\]?\s*([A-ZÇĞİÖŞÜ])\s*Şubesi", footer_text)
    if match:
        sinif = match.group(1)
        sube = match.group(2)
        return sinif, sube

    # Alternatif: boşlukla ayrılmış, örn: "Ana Sınıfı A Şubesi" veya "1. Sınıf B Şubesi"
    match2 = re.search(r"(Ana Sınıfı|\d+\. Sınıf)\s*([A-ZÇĞİÖŞÜ])\s*Şubesi", footer_text)
    if match2:
        sinif = match2.group(1)
        sube = match2.group(2)
        return sinif, sube

    return "Bilinmeyen Sınıf", "X"

def save_individual_pdfs_by_sube(input_pdf_path, base_folder="kisiler"):
    reader = PdfReader(input_pdf_path)
    os.makedirs(base_folder, exist_ok=True)

    ranges = get_individual_ranges(input_pdf_path)
    print(f"{len(ranges)} kişi bulundu.")

    klasor_sayac = defaultdict(int)

    for global_idx, (start, end) in enumerate(ranges, start=1):
        writer = PdfWriter()
        page_count = end - start + 1

        first_page_text = reader.pages[start].extract_text() or ""
        sinif, sube = extract_sinif_sube_from_footer(first_page_text)

        klasor_adi = f"{sinif} {sube}"
        klasor_path = os.path.join(base_folder, klasor_adi)
        os.makedirs(klasor_path, exist_ok=True)

        klasor_sayac[klasor_adi] += 1
        kisi_no = klasor_sayac[klasor_adi]

        for i in range(start, end + 1):
            page = reader.pages[i]
            # Cropbox sıfırlama
            page.cropbox.lower_left = page.mediabox.lower_left
            page.cropbox.upper_right = page.mediabox.upper_right
            writer.add_page(page)

        if page_count % 2 == 1:
            blank_page = PageObject.create_blank_page(
                width=reader.pages[0].mediabox.width,
                height=reader.pages[0].mediabox.height
            )
            writer.add_page(blank_page)

        output_path = os.path.join(klasor_path, f"kisi_{kisi_no:04}.pdf")
        with open(output_path, "wb") as f:
            writer.write(f)
        print(f"{output_path} kaydedildi. (klasör: {klasor_adi}, kişi: {kisi_no}, {page_count} sayfa{' +1 boş' if page_count % 2 == 1 else ''})")

    return sorted(klasor_sayac.keys())

def merge_by_sube(base_folder="kisiler", output_file="birlesik_dosya.pdf"):
    writer = PdfWriter()
    klasorlar = sorted([d for d in os.listdir(base_folder) if os.path.isdir(os.path.join(base_folder, d))])

    for klasor in klasorlar:
        klasor_path = os.path.join(base_folder, klasor)
        pdf_files = sorted(f for f in os.listdir(klasor_path) if f.endswith(".pdf"))
        print(f"{klasor} klasörü: {len(pdf_files)} dosya eklenecek.")

        for file in pdf_files:
            path = os.path.join(klasor_path, file)
            reader = PdfReader(path)
            for page in reader.pages:
                writer.add_page(page)

    with open(output_file, "wb") as f:
        writer.write(f)
    print(f"Tüm klasörler birleştirildi → {output_file}")

# === Çalıştır ===
input_pdf = "tam_dosya.pdf"
save_individual_pdfs_by_sube(input_pdf)
merge_by_sube()

5 Beğeni