لجمع الخلية نفسها من جداول مخزون متكررة، صدّر كل جدول بصيغة CSV، ثم شغّل اختصار Finder يقرأ ذلك الموضع وينشئ نظرة عامة. يجمع هذا الشرح الخلية B3، ويحتفظ باسم كل ملف مصدر، ويرفض الكتابة فوق نتيجة موجودة.

اختيار المدخلات المناسبة قبل إنشاء الاختصار

هذا الإجراء موجّه إلى من يدير عدة جداول مخزون بالتخطيط نفسه ويريد صفًا واحدًا لكل جدول في نظرة عامة منفصلة. يستخدم المثال ثلاثة ملفات مؤقتة تحتوي على أعداد اصطناعية. يمثّل كل ملف جدولًا مُصدّرًا؛ والخلية المستهدفة تقع في العمود B والصف 3، مع احتساب صف العناوين.

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

يفوّض الاختصار أدناه استخراج البيانات إلى برنامج Python صغير. فهو لا يتعامل مع مستند Numbers أو مصنف Excel على أنه نص عادي، ولا يفترض أن قبول إجراءٍ لملف جدول بيانات يمنحه إمكانية الوصول إلى خلاياه. توضّح Apple كيفية فحص المدخلات التي يقبلها الإجراء ومخرجاته الناتجة من خلال لوحة المعلومات. استخدم تلك اللوحة عند التحقق من الإجراءات المتاحة على Mac لديك. التنقل في قائمة الإجراءات في الاختصارات على Mac.

استخدم جدول القرار هذا قبل البدء:

نقطة البداية التحضير لهذا الإجراء
جدول واحد مطابق في كل مستند Numbers صدّر كل جدول بصيغة CSV.
عدة جداول مطابقة في مستند واحد صدّر ملفات CSV منفصلة وحدد الجداول المقصودة.
ملفات CSV موجودة ومفصولة بفواصل تحقّق من الترميز والتخطيط والموضع المستهدف.
تخطيطات مختلفة أو صفوف مخزون متغيرة وحّد الأمثلة المؤقتة أولًا؛ فالإحداثية الثابتة وحدها لا تحدد الكمية المقصودة.

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

تجهيز ملفات مخزون مؤقتة

تحتاج إلى تثبيت Python 3 بشكل منفصل لهذا المثال. يضع المثبّت القياسي من موقع Python روابط الملفات التنفيذية في /usr/local/bin/. تستخدم الأوامر أدناه /usr/local/bin/python3 صراحةً، لتجنب الاعتماد على مسار البحث عن الأوامر في الاختصار. اتبع تعليمات تثبيت إصدار Python المدعوم لديك، ثم تحقق من عمل هذا الأمر. استخدام Python على macOS.

/usr/local/bin/python3 --version

إذا لم يكن هذا المسار موجودًا، فأكمل تثبيت Python قبل المتابعة. لا يستخدم البرنامج سوى مكتبة Python القياسية؛ ولا يتطلب أي حزم إضافية. يشرح دليل Terminal من Apple إمكانية تشغيل الأوامر باستخدام المسار الكامل للملف التنفيذي متبوعًا بمعاملاته. تنفيذ الأوامر وتشغيل الأدوات في Terminal على Mac.

لإنشاء المدخلات الاصطناعية، الصق الأمر الكامل التالي في Terminal. ينشئ الأمر مجلد Inventory Demo على سطح المكتب ويتوقف إذا كان المجلد موجودًا بالفعل. استخدم مجلدًا مؤقتًا جديدًا بدلًا من دمج هذه الأمثلة في دليل موجود.

/usr/local/bin/python3 - <<'PY'
import csv
from pathlib import Path

root = Path.home() / "Desktop" / "Inventory Demo"
root.mkdir()
examples = [
    ("Birch", "A", "12"),
    ("Cedar", "B", "7"),
    ("Maple", "C", "0"),
]
for name, bin_name, count in examples:
    with (root / f"{name}.csv").open(
        "x", encoding="utf-8", newline=""
    ) as handle:
        csv.writer(handle).writerows([
            ["Item", "Value"],
            ["Bin", bin_name],
            ["Counted units", count],
        ])
print(root)
PY

لاختبار خطوة التصدير من Numbers بشكل منفصل، افتح أحد ملفات CSV المؤقتة في Numbers وصدّره إلى مجلد مؤقت آخر باستخدام File > Export To > CSV. اختر ملفًا لكل جدول، واترك Include table names غير محدد، واستخدم ترميز UTF-8. افحص الجدول المُصدّر للتأكد من أن A3 وB3 ما زالا يحتويان على التسمية والقيمة المقصودتين. توثّق Apple خيارات التصدير هذه. إعدادات التصدير في Numbers.

لا تغيّر امتداد جدول بيانات إلى .csv على سبيل التعويض عن تصديره. يتوقع هذا البرنامج نصًا مفصولًا بفواصل فعلية. احتفظ بملفات CSV الاصطناعية الأصلية الثلاثة معًا للشرح التالي.

إنشاء البرنامج الذي يبني النظرة العامة

احفظ البرنامج الكامل التالي باسم overview.py داخل Inventory Demo، باستخدام محرر نصوص عادي. تأكد من أن اسم الملف ينتهي بـ .py وليس .py.txt. يقبل البرنامج مسارات ملفات المصدر كمعاملات، ويقرأ B3، وينشئ overview.csv في المجلد المشترك بينها.

import csv
import io
import sys
from pathlib import Path

ROW, COLUMN = 2, 1  # Zero-based: B3
LABEL = "Counted units"

def build_overview(arguments):
    if not arguments:
        raise ValueError("Select at least one source CSV.")
    paths = [Path(name).expanduser().resolve(strict=True)
             for name in arguments]
    if len(set(paths)) != len(paths):
        raise ValueError("The same source was supplied twice.")
    if len({path.parent for path in paths}) != 1:
        raise ValueError("Keep all source CSVs in one folder.")
    rows = []
    for path in sorted(paths, key=lambda p: p.name):
        if (not path.is_file() or path.suffix.lower() != ".csv"
                or path.name.casefold() == "overview.csv"):
            raise ValueError(f"Not a source CSV: {path.name}")
        with path.open(encoding="utf-8-sig", newline="") as handle:
            records = list(csv.reader(handle, strict=True))
        if len(records) <= ROW or len(records[ROW]) <= COLUMN:
            raise ValueError(f"{path.name}: B3 does not exist.")
        if records[ROW][0] != LABEL:
            raise ValueError(f"{path.name}: A3 must be {LABEL!r}.")
        value = records[ROW][COLUMN]
        status = "blank" if value.strip() == "" else "present"
        rows.append([path.name, "B3", value, status])
    buffer = io.StringIO(newline="")
    writer = csv.writer(buffer)
    writer.writerow(["Source file", "Cell", "Value", "Status"])
    writer.writerows(rows)
    return paths[0].parent / "overview.csv", buffer.getvalue()

def main(arguments):
    try:
        destination, content = build_overview(arguments)
        with destination.open("x", encoding="utf-8", newline="") as handle:
            handle.write(content)
    except (OSError, ValueError, csv.Error) as error:
        print(f"Stopped: {error}", file=sys.stderr)
        return 1
    print(f"Created: {destination}")
    return 0

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

يستخدم البرنامج محلل CSV بدلًا من تقسيم النص عند الفواصل أو فواصل الأسطر. يعيد قارئ Python الحقول كسلاسل نصية، وتنص وثائقه على فتح ملفات CSV باستخدام newline="". وهذا يتيح التعامل مع الحقول الموضوعة بين علامتي اقتباس التي تحتوي على فواصل أو فواصل أسطر مضمنة. يحافظ البرنامج على القيمة المستخرجة دون جمعها أو تحويلها إلى رقم. قراءة ملفات CSV وكتابتها.

هناك عدة قيود مقصودة تجعل التحقق من النتيجة أسهل. يجب أن يكون كل ملف إدخال موجودًا، وأن تشترك جميع مسارات المصادر المحسوبة في المجلد نفسه، كما تُرفض المسارات المحسوبة المكررة. ويرتب البرنامج الملفات حسب الاسم بدلًا من الاعتماد على ترتيب تحديدها في Finder. ويرفض أيضًا إدخال ملف اسمه overview.csv، منعًا لإدراج النتيجة السابقة عن طريق الخطأ.

تُقرأ جميع المصادر ويُتحقق منها قبل بدء إنشاء المخرجات. يؤدي غياب B3 أو وجود تسمية غير متوقعة في A3 إلى إيقاف التشغيل. أما وجود B3 فارغ فينتج صفًا يحمل العلامة blank؛ وتظل القيمة 0 كما هي 0 وتحمل العلامة present. وهكذا تختلف نتائج الخلية الغائبة عن الخلية الفارغة وعن العدد صفر.

يستخدم الإخراج وضع الإنشاء الحصري، \"x\". توثّق Python أن هذا الوضع يفشل إذا كان الوجهة موجودة بالفعل. لذلك لا يستبدل البرنامج النظرة العامة السابقة ولا ينشئ اسمًا مرقمًا من تلقاء نفسه. ومع ذلك، قد يخلّف خطأ أثناء الكتابة الفعلية ملفًا جديدًا غير مكتمل؛ افحص أي ملف متبقٍ بعد خطأ كتابة قبل إعادة المحاولة. أوضاع فتح الملفات في Python.

ربط البرنامج باختصار Finder

أنشئ اختصارًا باسم Inventory Overview في تطبيق الاختصارات. افتح Details، وفعّل Use as Quick Action، ثم اختر Finder. في إعدادات الإدخال، أبقِ Files مفعّلًا وأوقف أنواع المحتوى الأخرى غير المرتبطة. توثّق Apple إتاحة Finder للاختصارات التي تقبل الملفات أو المجلدات، وكذلك عناصر التحكم لتقييد المدخلات المقبولة. تشغيل اختصار أثناء العمل على Mac، تقييد مدخلات الاختصار.

اضبط سلوك الاختصار عند عدم وجود مدخلات على Stop and Respond، واستخدم رسالة مثل Select the source CSV files in Finder. يمنع ذلك تحديدًا فارغًا من أن يصبح تشغيلًا ملتبسًا. يُشرح الخيار وحقل الرد في دليل إعدادات الإدخال من Apple. اختيار الاستجابة عند غياب المدخلات.

أضف الإجراء Run Shell Script. اضبط Shell على /bin/zsh، وصِل Input بـ Shortcut Input، واضبط Pass Input على as arguments. استبدل النص النموذجي بهذا الأمر الكامل:

/usr/local/bin/python3 "$HOME/Desktop/Inventory Demo/overview.py" "$@"

أبقِ علامات الاقتباس. يمرر \"$@\" الموضوع بين علامتي اقتباس المعاملات الواردة كلًا على حدة، مع الحفاظ على أسماء الملفات التي تحتوي على مسافات. ومسار البرنامج النصي محاط بعلامتي اقتباس للسبب نفسه. يوثّق دليل zsh المعاملات الموضعية والتوسيع المنفصل لعناصر المصفوفة الموضوعة بين علامتي اقتباس؛ كما يشرح دليل Terminal من Apple وضع المسارات بين علامتي اقتباس. المعاملات، تحديد الملفات والمجلدات في Terminal.

إذا طلب تطبيق الاختصارات تفعيل البرمجة النصية، فاختر Shortcuts > Settings > Advanced ثم حدد Allow Running Scripts. توثّق Apple هذا الإعداد ضمن السماح بتشغيل النصوص البرمجية من اختصار. الإعدادات المتقدمة للاختصارات.

يتكوّن التدفق المُعدّ من دخول كائنات الملفات المحددة إلى الاختصار، وتحويل مساراتها إلى معاملات للصدفة، ثم قراءة Python لتلك الملفات وكتابة النظرة العامة. والنتيجة النصية الناجحة لإجراء الصدفة هي رسالة Created: تتضمن مسار الوجهة. هذه الرسالة ليست ملف CSV نفسه. لا حاجة إلى إجراء حفظ لاحق لأن البرنامج أنشأ الملف بالفعل.

في Finder، حدد الملفات Birch.csv وCedar.csv وMaple.csv فقط. انقر على التحديد مع الضغط على Control واختر Quick Actions > Inventory Overview. إذا لم يظهر الاختصار، فاستخدم More > Customize لفحص امتدادات Finder المفعّلة، ثم أعد التحقق من أنواع المدخلات المقبولة. توثّق Apple تخصيص الإجراءات السريعة في Finder وإضافة الاختصارات إلى تلك القائمة. تنفيذ الإجراءات السريعة في Finder على Mac.

التحقق من النتيجة والتعامل مع مرات التشغيل المتكررة

افتح overview.csv من المجلد التجريبي في Numbers. وباستخدام الملفات الاصطناعية المرفقة، ينبغي أن يكون محتواه:

Source file,Cell,Value,Status
Birch.csv,B3,12,present
Cedar.csv,B3,7,present
Maple.csv,B3,0,present

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

اتبع تسلسل التشخيص هذا إذا اختلفت النتيجة:

  1. عدم ظهور الاختصار في Finder: تحقق من إعداد Finder، ومدخل Files المقبول، والامتداد المفعّل.
  2. ملف تنفيذي أو نص برمجي مفقود: تأكد من مسار Python ومن بقاء overview.py في مجلد العرض التوضيحي المحدد.
  3. غياب B3 أو خطأ A3: افحص السجلات المُصدّرة من المصدر وخيارات التصدير قبل تغيير البرنامج.
  4. ظهور قيمة فارغة غير متوقعة: افحص B3؛ فالبرنامج يترك القيم الفارغة كما هي عمدًا.
  5. وجود الوجهة مسبقًا: أعد تسمية النظرة العامة المؤقتة السابقة أو انقلها خارج مجلد المصدر قبل إعادة التشغيل.

يمكنك أيضًا استدعاء الاختصار نفسه من Terminal للتحقق من مسار الإدخال. توثّق Apple استخدام -i لتمرير مدخلات الملفات؛ أما تمرير مسار عبر قناة الإدخال فيمرر نصًا. استخدم الملفات الصريحة أدناه من دون خيار إخراج، لأن برنامج Python يتولى إنشاء المخرجات. وتظل قاعدة تعارض الاسم نفسها سارية. تشغيل الاختصارات من سطر الأوامر.

shortcuts run "Inventory Overview" -i \
  "$HOME/Desktop/Inventory Demo/Birch.csv" \
  "$HOME/Desktop/Inventory Demo/Cedar.csv" \
  "$HOME/Desktop/Inventory Demo/Maple.csv"

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

المصادر