المدونةسير العملقراءة في 6 دقائق

نموذج عربي ممسوح إلى نموذج وورد قابل للتعبئة: الحقول والتاريخ الهجري

حوّل النموذج الممسوح إلى وورد، ثم استبدل كل خط فراغ أو نقاط بعنصر تحكم في المحتوى من تبويب «المطور»: نص عادي للأسماء، وقائمة منسدلة للخيارات، ومنتقي تاريخ بتقويم هجري أو أم القرى. أعطِ كل حقل عنوانًا وعلامة، واقفله من الحذف، وقيّد التحرير، ثم جرّب النموذج كما يعبّئه الموظف.

في كثير من الإدارات نموذج قديم لا يملك أحد نسخته الأصلية: طلب إجازة، أو نموذج تعهد، أو استمارة بيانات موظف، أو طلب صرف. الموجود منه ورقة مطبوعة تُصوَّر وتُعبّأ بالقلم، أو ملف PDF ممسوح. وحين يُطلب أن يُعبّأ النموذج على الحاسوب ويُرسل بالبريد، يحوّله أحدهم إلى وورد فيحصل على نص سليم، لكن خطوط الفراغ فيه مجرد شرطات سفلية ونقاط. يكتب الموظف فوقها فتنزاح السطور، ويحذف بعضها خطأً، ويكتب التاريخ كل مرة بصيغة مختلفة.

هذا الدليل لموظف الشؤون الإدارية، ومكتب خدمات المستندات، ومن يُعدّ نماذج لجهة عمله. يشرح كيف تحوّل النموذج الممسوح إلى نموذج وورد قابل للتعبئة، بحقول حقيقية لا تنزاح ولا تُحذف، وكيف تتحقق منه قبل توزيعه.

الخطوة ١: حوّل النموذج إلى وورد وراجع نصه أولًا

ابدأ من أوضح نسخة لديك من النموذج: صفحة نظيفة غير معبّأة إن وجدت، لا نسخة عليها خط يد وأختام. حوّلها إلى وورد قابل للتعديل، ثم راجع النص على الصورة قبل أي عمل آخر: عناوين الحقول، والإقرارات، وأرقام المواد واللوائح المذكورة في أسفل النموذج. أي خطأ قراءة يبقى في النموذج الجديد سيتكرر في كل نسخة يعبّئها الموظفون. وإن كانت لديك عدة نماذج فجهّزها دفعة واحدة كما في دليل تجهيز دفعة المستندات الممسوحة.

احتفظ بالنسخة الممسوحة في المجلد نفسه مرجعًا. نموذج وورد الجديد نسخة عمل، والمرجع عند أي خلاف على صيغة بند هو الأصل المعتمد لدى جهتك.

الخطوة ٢: أظهر تبويب «المطور»

عناصر التحكم في المحتوى (Content Controls) موجودة في تبويب «المطور» (Developer)، وهو مخفي افتراضيًا. أظهره من «ملف» ← «خيارات» ← «تخصيص الشريط» ثم ضع علامة على «المطور». وتنبّه Microsoft إلى أن إنشاء النماذج القابلة للتعبئة غير متاح في Word للويب؛ صمّم النموذج في Word لسطح المكتب. وعلى Mac تتوفر أنواع أقل من العناصر (نص، وخانة اختيار، وقائمة مركبة).

الخطوة ٣: استبدل كل خط فراغ بالعنصر المناسب

احذف الشرطات السفلية أو النقاط بعد كل عنوان حقل، وضع مكانها عنصرًا من مجموعة «عناصر التحكم»:

في النموذج الورقيالعنصر في ووردملاحظة
الاسم، الإدارة، الرقم الوظيفينص عادي (Plain Text)سطر واحد بتنسيق ثابت
الملاحظات، المبرراتنص منسق (Rich Text)يسمح بفقرات
نوع الطلب: اعتيادية / اضطرارية / مرضيةقائمة منسدلة (Drop-Down List)يمنع كتابة خيار خارج القائمة
التاريخمنتقي التاريخ (Date Picker)انظر الخطوة ٤
«أقر بصحة البيانات» ☐خانة اختيار (Check Box)
الصورة الشخصيةصورة (Picture)

إن كان النموذج جدولًا من خانات (اسم في خانة وفراغه في الخانة المجاورة) فضع العنصر داخل خانة الفراغ، فيبقى الجدول ثابتًا من اليمين إلى اليسار مهما طال ما يُكتب. وإن كانت جهتك تحتاج النموذج مطبوعًا أيضًا فاعلم أن إطارات العناصر لا تُطبع، فقد تحتاج حدود خانات الجدول لتظهر أماكن الكتابة على الورق.

أما سطر «توقيع المدير المباشر» الذي يُوقَّع عليه باليد بعد الطباعة فلا يحتاج عنصرًا، ويمكنك ترك خطه كما هو عمدًا.

الخطوة ٤: التاريخ الهجري في منتقي التاريخ

حدد عنصر التاريخ ثم «المطور» ← «خصائص» (Properties). في خصائص منتقي التاريخ تختار لغة العرض وصيغة التاريخ ونوع التقويم. ملف وورد يحفظ نوع التقويم في الحقل نفسه، والمعيار (ISO/IEC 29500) يعرّف قيمًا منها gregorian وhijri وumalqura، وينص على أن التقويم إذا لم يُحدَّد فهو الميلادي. معنى ذلك عمليًا: إن كان عنوان الحقل «التاريخ (هـ)» ولم تغيّر نوع التقويم، فسيفتح للموظف تقويم ميلادي.

اختر التقويم الذي تعتمده جهتك، واكتب في عنوان الحقل نفسه «هـ» أو «م» حتى لا يلتبس الأمر على من يقرأ النموذج المطبوع. وإن كان النموذج يطلب التاريخين معًا فاجعلهما حقلين منفصلين لكل منهما تقويمه، ولا تعتمد على تحويل يدوي يكتبه الموظف.

الخطوة ٥: العنوان والعلامة والقفل لكل حقل

في نافذة «خصائص» لكل عنصر ثلاثة إعدادات تستحق دقيقة:

  • العنوان (Title): يظهر للموظف فوق الحقل حين يقف عليه. اكتب فيه اسم الحقل كما في النموذج.
  • العلامة (Tag): اسم داخلي لا يراه الموظف، لكنه ما يميّز الحقل إن أردت لاحقًا جمع بيانات النماذج المعبّأة بسكربت أو أداة. اجعله فريدًا وبحروف لاتينية، مثل employee_id. وإن نسخت حقلًا ولصقته لتصنع حقلًا جديدًا فغيّر علامته، لأن النسخ يكررها.
  • القفل: ضع علامة على «لا يمكن حذف عنصر التحكم في المحتوى» (Content control cannot be deleted)، فلا يحذف الموظف الحقل كله وهو يمسح ما كتبه.

الخطوة ٦: قيّد التحرير ثم جرّب النموذج

من «المطور» أو «مراجعة» اختر «تقييد التحرير» (Restrict Editing)، ثم اختر نوع التقييد، ثم «نعم، ابدأ بفرض الحماية» (Yes, Start Enforcing Protection). في القائمة خيار اسمه «تعبئة النماذج» (Filling in forms)، وهو نوع الحماية الذي تتطلبه حقول النماذج القديمة (Legacy form fields). وفي منتدى Microsoft Q&A ينبّه أحد المجيبين إلى أن الجمع بين تلك الحقول وعناصر التحكم في المحتوى لم يُصمَّم ليعمل معًا وقد يسبب سلوكًا غير متسق، ويقترح بدلًا منه «بلا تغييرات (قراءة فقط)» مع استثناءات.

وهذه طريقة الاستثناءات كما يشرحها دعم Microsoft: اختر «بلا تغييرات (قراءة فقط)»، ثم حدد كل حقل (أو الفقرة التي فيها الحقل) وضع علامة على «الجميع» (Everyone) تحت «الاستثناءات»، ثم ابدأ فرض الحماية. يبقى نص النموذج مقفلًا، وتبقى الحقول وحدها قابلة للكتابة. وكلمة المرور اختيارية؛ وإن وضعتها فاحفظها، فلا تستطيع Microsoft استعادتها.

أيًّا كان ما اخترته، افعل ما توصي به Microsoft: افتح النموذج المحمي، وعبّئه كما سيعبّئه الموظف، واحفظ نسخة. تأكد أنك تنتقل بين الحقول، وأن القائمة تفتح، وأن التقويم الصحيح يظهر، وأن نص النموذج نفسه لا يقبل التعديل.

ثم احفظه قالبًا (‎.dotx) حتى يفتح كل موظف نسخة جديدة فارغة، كما في دليل تحويل ورقة العمل الممسوحة إلى قالب.

افحص النموذج بسكربت قصير

بعد عشرات الحقول يسهل أن يفوتك خط فراغ لم يُستبدل، أو حقل بلا علامة، أو علامة مكررة من النسخ واللصق. هذا السكربت يقرأ ملف ‎.docx مباشرة (بايثون 3 دون مكتبات إضافية) ويطبع قائمة الحقول وما يستحق المراجعة:

import re
import sys
import zipfile
import xml.etree.ElementTree as ET

W = "{http://schemas.openxmlformats.org/wordprocessingml/2006/main}"
W14 = "{http://schemas.microsoft.com/office/word/2010/wordml}"
BLANK = re.compile(r"_{4,}|\.{4,}|…{2,}|ـ{4,}")
HIJRI = re.compile(r"هـ|هجري")


def text_of(el):
    return "".join(t.text or "" for t in el.iter(W + "t"))


def control_type(pr):
    for tag, name in (("date", "date"), ("dropDownList", "list"),
                      ("comboBox", "combo"), ("text", "text"),
                      ("picture", "picture")):
        if pr.find(W + tag) is not None:
            return name
    if pr.find(W14 + "checkbox") is not None:
        return "checkbox"
    return "rich-text"


def main(path):
    with zipfile.ZipFile(path) as z:
        body = ET.fromstring(z.read("word/document.xml")).find(W + "body")
        settings = ET.fromstring(z.read("word/settings.xml"))
    problems = []

    # 1) blank lines left as typed underscores or dots, outside any control
    sdt_paras = set()
    for sdt in body.iter(W + "sdt"):
        for p in sdt.iter(W + "p"):
            sdt_paras.add(p)
    for n, p in enumerate(body.iter(W + "p"), 1):
        plain = "".join(text_of(r) for r in p if r.tag == W + "r")
        if p not in sdt_paras and BLANK.search(plain):
            problems.append(f"paragraph {n}: typed blank left: {plain.strip()}")

    # 2) the controls themselves
    print("controls:")
    seen = {}
    for i, sdt in enumerate(body.iter(W + "sdt"), 1):
        pr = sdt.find(W + "sdtPr")
        kind = control_type(pr)
        tag = pr.find(W + "tag")
        alias = pr.find(W + "alias")
        lock = pr.find(W + "lock")
        tag = tag.get(W + "val") if tag is not None else ""
        alias = alias.get(W + "val") if alias is not None else ""
        lock = lock.get(W + "val") if lock is not None else "unlocked"
        extra = ""
        if kind == "date":
            cal = pr.find(W + "date/" + W + "calendar")
            cal = cal.get(W + "val") if cal is not None else "gregorian"
            fmt = pr.find(W + "date/" + W + "dateFormat")
            fmt = fmt.get(W + "val") if fmt is not None else ""
            extra = f" calendar={cal} format={fmt}"
            if HIJRI.search(alias) and cal not in ("hijri", "umalqura"):
                problems.append(f"control {i} ({alias or '-'}): Hijri label but calendar={cal}")
        if kind in ("list", "combo"):
            items = pr.findall(W + ("dropDownList" if kind == "list" else "comboBox")
                               + "/" + W + "listItem")
            extra = f" items={len(items)}"
            if len(items) < 2:
                problems.append(f"control {i} ({alias or '-'}): list with {len(items)} item(s)")
        print(f"  {i}. {kind:9} title={alias or '-'} tag={tag or '-'} lock={lock}{extra}")
        if not alias:
            problems.append(f"control {i}: no title (the filler sees no label)")
        if not tag:
            problems.append(f"control {i} ({alias or '-'}): no tag (data cannot be collected)")
        elif tag in seen:
            problems.append(f"control {i} ({alias or '-'}): tag '{tag}' repeats control {seen[tag]}")
        else:
            seen[tag] = i
        if lock not in ("sdtLocked", "sdtContentLocked"):
            problems.append(f"control {i} ({alias or '-'}): can be deleted (lock={lock})")

    # 3) protection
    prot = settings.find(W + "documentProtection")
    exceptions = len(list(body.iter(W + "permStart")))
    if prot is None or prot.get(W + "enforcement") not in ("1", "true", "on"):
        problems.append("document: protection not enforced")
    else:
        edit = prot.get(W + "edit")
        print(f"protection: edit={edit} exceptions={exceptions}")
        if edit == "forms" and seen:
            problems.append("document: 'filling in forms' with content controls: test it")
        if edit == "readOnly" and exceptions == 0:
            problems.append("document: read-only with no exceptions: nothing is fillable")

    print(f"\n{len(problems)} finding(s):")
    for line in problems:
        print("  - " + line)


if __name__ == "__main__":
    main(sys.argv[1])

شغّله هكذا:

python3 check_form.py نموذج-طلب-اجازة.docx

مثال توضيحي

جربنا السكربت في هذه الجلسة على ملفين صنعناهما يدويًا بصيغة WordprocessingML (لا على نموذج حقيقي ولا على ملف من ScribeTools). الأول «نموذج طلب إجازة» فيه أخطاء متعمدة: رقم وظيفي تُرك خطًّا من الشرطات، وحقل «الإدارة» بلا علامة ولا قفل، وتاريخ عنوانه «(هـ)» بلا تقويم محدد، وقائمة بخيار واحد، وحقل منسوخ بلا عنوان كرر علامة حقل الاسم، ولا حماية. هذه مخرجاته كما ظهرت:

controls:
  1. text      title=اسم الموظف tag=employee_name lock=sdtLocked
  2. text      title=الإدارة tag=- lock=unlocked
  3. date      title=تاريخ بداية الإجازة (هـ) tag=start_date lock=sdtLocked calendar=gregorian format=dd/MM/yyyy
  4. list      title=نوع الإجازة tag=leave_type lock=sdtLocked items=1
  5. text      title=- tag=employee_name lock=sdtLocked

9 finding(s):
  - paragraph 3: typed blank left: الرقم الوظيفي: ____________
  - paragraph 8: typed blank left: توقيع المدير المباشر: ....................
  - control 2 (الإدارة): no tag (data cannot be collected)
  - control 2 (الإدارة): can be deleted (lock=unlocked)
  - control 3 (تاريخ بداية الإجازة (هـ)): Hijri label but calendar=gregorian
  - control 4 (نوع الإجازة): list with 1 item(s)
  - control 5: no title (the filler sees no label)
  - control 5 (-): tag 'employee_name' repeats control 1
  - document: protection not enforced

لاحظ أن السطر الأخير من قسم الخط (توقيع المدير المباشر) ظهر أيضًا؛ هذا سطر يُوقَّع باليد فتركه مقصود. السكربت يعرض، وأنت تقرر.

والملف الثاني النموذج نفسه بعد الإصلاح: كل حقل بعنوان وعلامة فريدة وقفل، والتاريخ بتقويم أم القرى، والقائمة بثلاثة خيارات، والحماية «قراءة فقط» مع استثناء لكل حقل، وسطر التوقيع بلا خط:

controls:
  1. text      title=اسم الموظف tag=employee_name lock=sdtLocked
  2. text      title=الرقم الوظيفي tag=employee_id lock=sdtLocked
  3. text      title=الإدارة tag=department lock=sdtLocked
  4. date      title=تاريخ بداية الإجازة (هـ) tag=start_date lock=sdtLocked calendar=umalqura format=dd/MM/yyyy
  5. list      title=نوع الإجازة tag=leave_type lock=sdtLocked items=3
  6. text      title=اسم البديل tag=substitute_name lock=sdtLocked
  7. checkbox  title=أقر بصحة البيانات tag=declaration lock=sdtLocked
protection: edit=readOnly exceptions=7

0 finding(s):

قائمة مراجعة قبل توزيع النموذج

  • نص النموذج روجع على الأصل الممسوح: العناوين والإقرارات وأرقام المواد
  • لا يبقى خط فراغ أو نقاط إلا ما يُوقَّع عليه باليد عمدًا
  • كل حقل له عنوان يطابق النموذج، وعلامة فريدة
  • الخيارات المحدودة قوائم منسدلة بكل الخيارات، لا نص حر
  • كل حقل تاريخ بالتقويم الصحيح، و«هـ» أو «م» في عنوانه
  • الحقول مقفلة من الحذف، والتحرير مقيّد، والنموذج جُرّب محميًّا
  • الجدول ثابت من اليمين إلى اليسار بعد كتابة قيم طويلة في الحقول
  • النموذج محفوظ قالبًا ‎.dotx، والأصل الممسوح محفوظ بجانبه

أين يدخل ScribeTools

يحوّل ScribeTools الصفحات العربية الممسوحة إلى وورد قابل للتعديل، فتبدأ من نص النموذج وجداوله بدل إعادة كتابته. أما الحقول والتقويم والحماية فتضيفها أنت في وورد بالخطوات أعلاه. وراجع الناتج على الأصل دائمًا قبل الاعتماد عليه. وإن كان المستند عقدًا لا نموذجًا فاتبع دليل مراجعة العقد الممسوح بعد تحويله.

حدود هذا الدليل

  • تقييد التحرير في وورد يمنع التغيير غير المقصود فقط. المعيار نفسه ينص على أنه لا يشفّر المستند وليس ميزة أمان، ويمكن لتطبيقات أخرى تجاوزه. لا تعتمد عليه لحماية بيانات حساسة.
  • نموذج وورد المعبّأ لا يكتسب صفة رسمية بمجرد تعبئته؛ اعتماد النموذج وتوقيعه يتبعان إجراءات جهتك.
  • لم نختبر خطوات واجهة وورد في هذه الجلسة؛ هي منقولة عن توثيق Microsoft، وأسماء الأوامر تختلف بين الإصدارات ولغات الواجهة وبين Windows وMac.
  • السكربت يقرأ متن المستند فقط، لا الرؤوس والتذييلات ومربعات النص، ويتعرف على خطوط الفراغ المكتوبة بالشرطات السفلية والنقاط والتطويل فقط. ويعدّ الاستثناءات ولا يتحقق من أن كل حقل داخل استثناء؛ هذا تكشفه تجربة النموذج محميًّا.

المصادر

  1. Microsoft Support: Create forms that users complete or print in Word
  2. Microsoft Support: Allow changes to parts of a protected document
  3. Microsoft Q&A: Filling in forms with restricted editing
  4. Microsoft Learn (Open XML / ISO/IEC 29500): CalendarValues — hijri, umalqura
  5. Microsoft Learn (Open XML / ISO/IEC 29500): Calendar (Date Picker Calendar Type)
  6. Microsoft Learn (Open XML / ISO/IEC 29500): LockingValues — sdtLocked
  7. Microsoft Learn (Open XML / ISO/IEC 29500): DocumentProtection