معادن · الصيانة الميكانيكية PAP · Power BI

دليل بناء Maintenance Hub

كل شي تحتاجينه عشان تبنين اللوحة الموحدة من الصفر في جهاز الدوام: المصادر، والجداول، والعلاقات، وكل مقياس بكوده، وكل visual بمكانه ومقاسه بالبكسل. الكود والأرقام مأخوذة من الملف نفسه مباشرة.

6 صفحات19 جدول109 مقياس148 visualالمقاس 1280 × 720

قبل ما تبدين

الصورة الكاملة

ملف Power BI واحد فيه ست صفحات، كل صفحة لها خلفية مرسومة (الشريط الجانبي، واللوحات البيضاء، والعناوين الثابتة)، وفوقها visuals شفافة. التنقل من الشريط الداكن على اليسار.

خلفية صفحة الصفحة الرئيسية
الصفحة الرئيسية · Homeوين المشكلة اليوم؟ خمس بطاقات، كل وحدة تفتح صفحتها.
المصدر: كل المصادر
خلفية صفحة الاجتماع الصباحي
الاجتماع الصباحي · Daily meetingإنتاج أمس مقابل الهدف، السلامة، خطة اليوم، المخاوف، ومراقبة الحالة.
المصدر: Daily_Inputs.xlsx
خلفية صفحة حماية HEMAYA
حماية HEMAYA · HEMAYAوش انرصد، ووين، وليش، وكيف انقفل، ومتى.
المصدر: Daily_Inputs.xlsx ← tblHEMAYA_Log
خلفية صفحة الحضور
الحضور · Attendanceمين موجود، ووين، وبأي شفت، يوم أو أسبوع أو شهر.
المصدر: PAP_Attendance.xlsx
خلفية صفحة أوامر العمل
أوامر العمل · Work ordersنسبة الوقائي، الطوارئ، الالتزام بالجدول، عمر المفتوح، وأكثر المعدات أعطالًا.
المصدر: Fact_WorkOrders.csv
خلفية صفحة قطع الغيار
قطع الغيار · Spare partsصحة المخزون، القطع الحرجة، واللي في الإصلاح أو الطلب.
المصدر: Daily_Inputs.xlsx ← tblSpares_Register
الفكرة اللي تخلي الشكل احترافيكل الأشكال الثابتة (اللوحات، الظلال، الأيقونات، الشريط الجانبي) مرسومة داخل صورة PNG وحدة لكل صفحة. والـ visuals فوقها بدون خلفية ولا إطار. كذا الصفحة خفيفة، والمحاذاة مضبوطة، والشكل ما يتغير.

ترتيب البناء

  1. المصادر وPower Query: الجداول نظيفة وبأنواع صحيحة.
  2. النموذج: العلاقات، والترتيب، وإخفاء الأعمدة المساعدة.
  3. المقاييس: كلها في جدول واحد مقسمة بمجلدات.
  4. الغلاف: الثيم، ومقاس الصفحة، والخلفية، وأزرار التنقل.
  5. الصفحات: visual visual بمكانه ومقاسه.
  6. التحديث والنشر.

اللي تنقلينه لجهاز الدوام

حقيبة البناء

جهزت لك مجلد 09_Maintenance_Hub\6_Build_Kit. انقليه مع ملفات البيانات.

الملفوش هووين يروح
6_Build_Kit\backgrounds\bg_*.png6 خلفيات، كل وحدة 2560×1440Image visual بحجم الصفحة (المرحلة 4)
6_Build_Kit\theme\Hub_Theme.jsonثيم اللوحة: ألوان معادن والخطوطView ← Themes ← Browse for themes
05_Daily_Meeting\1_Working\Daily_Inputs.xlsx8 جداول: HEMAYA، قطع الغيار، السلامة، الإنتاج…OneDrive القسم
02_Attendance\1_Working\PAP_Attendance.xlsxtblEmployees و tblAttendanceOneDrive القسم
01_WorkOrders\1_Model\Fact_WorkOrders.csv و Dim_Asset.csvأوامر العمل والمعداتOneDrive القسم
_Brand\DIN-Next-LT-Pro-Regular.ttfخط الأرقام الكبيرةاختياري: إذا مو مثبت يطلع Segoe UI Semibold بداله

المرحلة 1

المصادر وPower Query

النمط اللي يتكرر في كل جدول

كل جدول من Excel يمشي بنفس الخطوات. افهميها مرة وحدة، والباقي تكرار:

الخطوةوش تسويليش
Sourceيفتح الملففي جهاز الدوام يكون من رابط OneDrive
Tياخذ الجدول باسمه، مثل tblHEMAYA_Logالجدول يتمدد مع البيانات، والشيت لا
KeptChoose Columns: الأعمدة المطلوبة بسلو أحد أضاف عمود في Excel ما ينكسر شي
NoBlankيشيل الصفوف اللي عمودها الأساسي فاضيجداول Excel فيها صفوف فاضية جاهزة للإدخال
Typedيحدد نوع كل عمودالتاريخ Date والأرقام Number، وإلا الحسابات تغلط
A1… B1…أعمدة محسوبةالحسابات الثابتة لكل صف مكانها هنا مو في DAX
في جهاز الدوام: غيري أول سطر بسالكود هنا يقرأ من مسار جهازك الشخصي File.Contents("C:\\Users\\rawab\\…"). في الدوام استخدمي Get Data ← Web ← رابط الملف من OneDrive، فيصير أول سطر:
Source = Excel.Workbook(Web.Contents("https://…sharepoint.com/…/Daily_Inputs.xlsx"), null, true),
والـ CSV: Csv.Document(Web.Contents("…/Fact_WorkOrders.csv"), [Delimiter=",", Encoding=65001]). باقي الخطوات تبقى مثل ما هي.

طريقة النسخ

Home ← New Source ← Blank Query ← Advanced Editor ← الصقي الكود ← عدلي سطر Source ← Done ← سمّي الاستعلام بنفس اسم الجدول بالضبط.

مصادر Daily_Inputs.xlsx

HEMAYA_Log · سجل ملاحظات وحوادث حماية30 عمود
IsClosed
1 إذا الحالة Closed. تستخدمه المقاييس والتلوين.
Days open
من تاريخ الرصد إلى الإغلاق، أو إلى آخر تاريخ رصد إذا للحين مفتوح.
Overdue
1 إذا مو مقفل وتاريخ الهدف فات.
Closed on time
1 إذا انقفل قبل أو في تاريخ الهدف.
Age bucket / AgeSort
فئات العمر: 0-7، 8-14، 15-30، 31-60، 60+ يوم، مع رقم للترتيب.
Month / MonthSort
الشهر كنص (Sep 26) ورقم للترتيب (202609).
SeveritySort
Critical=1 … Low=4 عشان الترتيب يكون منطقي مو أبجدي.
let
    Source = Excel.Workbook(File.Contents("C:\\Users\\rawab\\OneDrive\\Desktop\\معادن - روابي\\05_Daily_Meeting\\1_Working\\Daily_Inputs.xlsx"), null, true),
    T = Source{[Item="tblHEMAYA_Log", Kind="Table"]}[Data],
    Kept = Table.SelectColumns(T, {"ID", "Reported", "Area", "Location", "Equipment", "Type", "Category", "Severity", "What happened", "Root cause (why)", "Immediate action", "Corrective action (how closed)", "Raised by", "Owner", "Target date", "Closed date", "Status", "Verified by", "Source"}),
    NoBlank = Table.SelectRows(Kept, each Record.Field(_, "ID") <> null and Record.Field(_, "ID") <> ""),
    Typed = Table.TransformColumnTypes(NoBlank, {{"ID", type text}, {"Reported", type date}, {"Area", type text}, {"Location", type text}, {"Equipment", type text}, {"Type", type text}, {"Category", type text}, {"Severity", type text}, {"What happened", type text}, {"Root cause (why)", type text}, {"Immediate action", type text}, {"Corrective action (how closed)", type text}, {"Raised by", type text}, {"Owner", type text}, {"Target date", type date}, {"Closed date", type date}, {"Status", type text}, {"Verified by", type text}, {"Source", type text}}),
    Ref = List.Max(Typed[Reported]),
    A1 = Table.AddColumn(Typed, "IsClosed", each if [Status] = "Closed" then 1 else 0, Int64.Type),
    A2 = Table.AddColumn(A1, "Days open", each if [Closed date] <> null then Duration.Days([Closed date] - [Reported]) else Duration.Days(Ref - [Reported]), Int64.Type),
    A3 = Table.AddColumn(A2, "Overdue", each if [Status] <> "Closed" and [Target date] <> null and [Target date] < Ref then 1 else 0, Int64.Type),
    A4 = Table.AddColumn(A3, "Closed on time", each if [Closed date] <> null and [Target date] <> null and [Closed date] <= [Target date] then 1 else 0, Int64.Type),
    A5 = Table.AddColumn(A4, "Age bucket", each if [Status] = "Closed" then "Closed" else if [Days open] <= 7 then "0-7 days" else if [Days open] <= 14 then "8-14 days" else if [Days open] <= 30 then "15-30 days" else if [Days open] <= 60 then "31-60 days" else "60+ days", type text),
    A6 = Table.AddColumn(A5, "AgeSort", each if [Status] = "Closed" then 9 else if [Days open] <= 7 then 1 else if [Days open] <= 14 then 2 else if [Days open] <= 30 then 3 else if [Days open] <= 60 then 4 else 5, Int64.Type),
    A7 = Table.AddColumn(A6, "Month", each Date.ToText([Reported], "MMM yy"), type text),
    A8 = Table.AddColumn(A7, "MonthSort", each Date.Year([Reported]) * 100 + Date.Month([Reported]), Int64.Type),
    A9 = Table.AddColumn(A8, "SeveritySort", each if [Severity] = "Critical" then 1 else if [Severity] = "High" then 2 else if [Severity] = "Medium" then 3 else 4, Int64.Type),
    A10 = Table.NestedJoin(A9, {"Owner"}, HEMAYA_People, {"Name"}, "OP", JoinKind.LeftOuter),
    A11 = Table.ExpandTableColumn(A10, "OP", {"Department"}, {"Owner dept"}),
    A12 = Table.NestedJoin(A11, {"Raised by"}, HEMAYA_People, {"Name"}, "RP", JoinKind.LeftOuter),
    A13 = Table.ExpandTableColumn(A12, "RP", {"Department"}, {"Raised dept"}),
    A14 = Table.ReplaceValue(A13, null, "Other", Replacer.ReplaceValue, {"Owner dept", "Raised dept"})
in
    A14
Spares_Register · سجل قطع الغيار27 عمود
Stock health / HealthSort
Out of stock · Below minimum · Reorder now · Under repair · On order · Healthy، مع ترتيب.
Stock value SAR
الكمية × سعر الوحدة.
Days since movement
من آخر حركة إلى اليوم.
Days to expected
من اليوم إلى تاريخ الرجوع المتوقع (سالب = تأخر).
Return overdue
1 إذا في الإصلاح أو الطلب وتاريخه فات.
Stock % of max
الكمية ÷ الحد الأعلى.
let
    Source = Excel.Workbook(File.Contents("C:\\Users\\rawab\\OneDrive\\Desktop\\معادن - روابي\\05_Daily_Meeting\\1_Working\\Daily_Inputs.xlsx"), null, true),
    T = Source{[Item="tblSpares_Register", Kind="Table"]}[Data],
    Kept = Table.SelectColumns(T, {"Part No", "Description", "Equipment", "Area", "Category", "Criticality", "Location", "Qty on hand", "Min", "Max", "Reorder point", "Unit cost SAR", "Lead time days", "Status", "Repair / order ref", "Sent / ordered", "Expected date", "Last movement", "Note", "Source"}),
    NoBlank = Table.SelectRows(Kept, each Record.Field(_, "Part No") <> null and Record.Field(_, "Part No") <> ""),
    Typed = Table.TransformColumnTypes(NoBlank, {{"Part No", type text}, {"Description", type text}, {"Equipment", type text}, {"Area", type text}, {"Category", type text}, {"Criticality", type text}, {"Location", type text}, {"Qty on hand", type number}, {"Min", type number}, {"Max", type number}, {"Reorder point", type number}, {"Unit cost SAR", type number}, {"Lead time days", type number}, {"Status", type text}, {"Repair / order ref", type text}, {"Sent / ordered", type date}, {"Expected date", type date}, {"Last movement", type date}, {"Note", type text}, {"Source", type text}}),
    Ref = Date.From(DateTime.LocalNow()),
    B1 = Table.AddColumn(Typed, "Stock health", each if [Status] = "Under repair (CWS)" then "Under repair" else if [Status] = "On order" and [Qty on hand] <= [Reorder point] then "On order" else if [Qty on hand] = 0 then "Out of stock" else if [Qty on hand] < [Min] then "Below minimum" else if [Qty on hand] <= [Reorder point] then "Reorder now" else "Healthy", type text),
    B2 = Table.AddColumn(B1, "HealthSort", each if [Stock health] = "Out of stock" then 1 else if [Stock health] = "Below minimum" then 2 else if [Stock health] = "Reorder now" then 3 else if [Stock health] = "Under repair" then 4 else if [Stock health] = "On order" then 5 else 6, Int64.Type),
    B3 = Table.AddColumn(B2, "Stock value SAR", each [Qty on hand] * [Unit cost SAR], type number),
    B4 = Table.AddColumn(B3, "Days since movement", each if [Last movement] = null then null else Duration.Days(Ref - [Last movement]), Int64.Type),
    B5 = Table.AddColumn(B4, "Days to expected", each if [Expected date] = null then null else Duration.Days([Expected date] - Ref), Int64.Type),
    B6 = Table.AddColumn(B5, "Return overdue", each if ([Status] = "Under repair (CWS)" or [Status] = "On order") and [Expected date] <> null and [Expected date] < Ref then 1 else 0, Int64.Type),
    B7 = Table.AddColumn(B6, "Stock % of max", each if [Max] = null or [Max] = 0 then null else [Qty on hand] / [Max], type number)
in
    B7
Safety_Daily · أرقام السلامة اليومية8 عمود
let
    Source = Excel.Workbook(File.Contents("C:\\Users\\rawab\\OneDrive\\Desktop\\معادن - روابي\\05_Daily_Meeting\\1_Working\\Daily_Inputs.xlsx"), null, true),
    T = Source{[Item="tblSafety_Daily", Kind="Table"]}[Data],
    Kept = Table.SelectColumns(T, {"Date", "Area", "Unsafe conditions", "Unsafe acts", "HEMAYA assigned", "HEMAYA closed", "Incidents", "Major event / note"}),
    NoBlank = Table.SelectRows(Kept, each Record.Field(_, "Date") <> null and Record.Field(_, "Date") <> ""),
    Typed = Table.TransformColumnTypes(NoBlank, {{"Date", type date}, {"Area", type text}, {"Unsafe conditions", type number}, {"Unsafe acts", type number}, {"HEMAYA assigned", type number}, {"HEMAYA closed", type number}, {"Incidents", type number}, {"Major event / note", type text}})
in
    Typed
LLF_Log · ملاحظات LLF7 عمود
let
    Source = Excel.Workbook(File.Contents("C:\\Users\\rawab\\OneDrive\\Desktop\\معادن - روابي\\05_Daily_Meeting\\1_Working\\Daily_Inputs.xlsx"), null, true),
    T = Source{[Item="tblLLF_Log", Kind="Table"]}[Data],
    Kept = Table.SelectColumns(T, {"Date", "Area", "Equipment", "Finding", "Raised by", "Status", "Closed date"}),
    NoBlank = Table.SelectRows(Kept, each Record.Field(_, "Date") <> null and Record.Field(_, "Date") <> ""),
    Typed = Table.TransformColumnTypes(NoBlank, {{"Date", type date}, {"Area", type text}, {"Equipment", type text}, {"Finding", type text}, {"Raised by", type text}, {"Status", type text}, {"Closed date", type date}})
in
    Typed
Production_Daily · الإنتاج والتوقف اليومي7 عمود
let
    Source = Excel.Workbook(File.Contents("C:\\Users\\rawab\\OneDrive\\Desktop\\معادن - روابي\\05_Daily_Meeting\\1_Working\\Daily_Inputs.xlsx"), null, true),
    T = Source{[Item="tblProduction_Daily", Kind="Table"]}[Data],
    Kept = Table.SelectColumns(T, {"Date", "Area", "Target MT", "Actual MT", "Downtime hrs", "Major maintenance", "Note"}),
    NoBlank = Table.SelectRows(Kept, each Record.Field(_, "Date") <> null and Record.Field(_, "Date") <> ""),
    Typed = Table.TransformColumnTypes(NoBlank, {{"Date", type date}, {"Area", type text}, {"Target MT", type number}, {"Actual MT", type number}, {"Downtime hrs", type number}, {"Major maintenance", type text}, {"Note", type text}})
in
    Typed
Activities · أنشطة اليوم8 عمود
let
    Source = Excel.Workbook(File.Contents("C:\\Users\\rawab\\OneDrive\\Desktop\\معادن - روابي\\05_Daily_Meeting\\1_Working\\Daily_Inputs.xlsx"), null, true),
    T = Source{[Item="tblActivities", Kind="Table"]}[Data],
    Kept = Table.SelectColumns(T, {"Date", "Area", "When", "Activity", "Work order", "Crew", "Status", "Note"}),
    NoBlank = Table.SelectRows(Kept, each Record.Field(_, "Date") <> null and Record.Field(_, "Date") <> ""),
    Typed = Table.TransformColumnTypes(NoBlank, {{"Date", type date}, {"Area", type text}, {"When", type text}, {"Activity", type text}, {"Work order", type text}, {"Crew", type number}, {"Status", type text}, {"Note", type text}})
in
    Typed
Concerns · المخاوف والمتابعات7 عمود
let
    Source = Excel.Workbook(File.Contents("C:\\Users\\rawab\\OneDrive\\Desktop\\معادن - روابي\\05_Daily_Meeting\\1_Working\\Daily_Inputs.xlsx"), null, true),
    T = Source{[Item="tblConcerns", Kind="Table"]}[Data],
    Kept = Table.SelectColumns(T, {"Date", "Area", "Concern / highlight", "Owner", "Due", "Status", "Note"}),
    NoBlank = Table.SelectRows(Kept, each Record.Field(_, "Date") <> null and Record.Field(_, "Date") <> ""),
    Typed = Table.TransformColumnTypes(NoBlank, {{"Date", type date}, {"Area", type text}, {"Concern / highlight", type text}, {"Owner", type text}, {"Due", type date}, {"Status", type text}, {"Note", type text}})
in
    Typed
CM_Alerts · تنبيهات مراقبة الحالة8 عمود
let
    Source = Excel.Workbook(File.Contents("C:\\Users\\rawab\\OneDrive\\Desktop\\معادن - روابي\\05_Daily_Meeting\\1_Working\\Daily_Inputs.xlsx"), null, true),
    T = Source{[Item="tblCM_Alerts", Kind="Table"]}[Data],
    Kept = Table.SelectColumns(T, {"Date", "Area", "Asset", "Parameter", "Level", "Value", "Action", "Status"}),
    NoBlank = Table.SelectRows(Kept, each Record.Field(_, "Date") <> null and Record.Field(_, "Date") <> ""),
    Typed = Table.TransformColumnTypes(NoBlank, {{"Date", type date}, {"Area", type text}, {"Asset", type text}, {"Parameter", type text}, {"Level", type text}, {"Value", type number}, {"Action", type text}, {"Status", type text}})
in
    Typed

مصادر الحضور

Attendance · سجل الحضور12 عمود
C1 / C2
Area الفاضية أو 0 تصير (No area) عشان ما تختفي من التقارير.
Presence / PresenceSort
حالة مفهومة للعرض: On site، Absent، Sick leave، Permission، Vacation، Day off.
let
    Source = Excel.Workbook(File.Contents("C:\\Users\\rawab\\OneDrive\\Desktop\\معادن - روابي\\02_Attendance\\1_Working\\PAP_Attendance.xlsx"), null, true),
    T = Source{[Item="tblAttendance", Kind="Table"]}[Data],
    Kept = Table.SelectColumns(T, {"Date", "EmployeeID", "EmployeeName", "Area", "Craft", "Level", "DefaultShift", "Status", "Shift", "On Site"}),
    NoBlank = Table.SelectRows(Kept, each Record.Field(_, "EmployeeID") <> null and Record.Field(_, "EmployeeID") <> ""),
    Typed = Table.TransformColumnTypes(NoBlank, {{"Date", type date}, {"EmployeeID", type text}, {"EmployeeName", type text}, {"Area", type text}, {"Craft", type text}, {"Level", type text}, {"DefaultShift", type text}, {"Status", type text}, {"Shift", type text}, {"On Site", type number}}),
    C1 = Table.ReplaceValue(Typed, "0", "(No area)", Replacer.ReplaceValue, {"Area"}),
    C2 = Table.ReplaceValue(C1, null, "(No area)", Replacer.ReplaceValue, {"Area"}),
    C3 = Table.AddColumn(C2, "Presence", each if [On Site] = 1 then "On site" else if [Status] = "Absent" then "Absent" else if [Status] = "Sick Leave" then "Sick leave" else if [Status] = "Vacation" then "Vacation" else if [Status] = "Off" then "Day off" else if [Status] = "Permission" then "Permission" else "Other", type text),
    C4 = Table.AddColumn(C3, "PresenceSort", each if [Presence] = "On site" then 1 else if [Presence] = "Absent" then 2 else if [Presence] = "Sick leave" then 3 else if [Presence] = "Permission" then 4 else if [Presence] = "Vacation" then 5 else if [Presence] = "Day off" then 6 else 7, Int64.Type)
in
    C4
Employees · الموظفين8 عمود
let
    Source = Excel.Workbook(File.Contents("C:\\Users\\rawab\\OneDrive\\Desktop\\معادن - روابي\\02_Attendance\\1_Working\\PAP_Attendance.xlsx"), null, true),
    T = Source{[Item="tblEmployees", Kind="Table"]}[Data],
    Kept = Table.SelectColumns(T, {"EmployeeID", "EmployeeName", "Craft", "Level", "Area", "DefaultShift", "ContractType", "EmploymentStatus"}),
    NoBlank = Table.SelectRows(Kept, each Record.Field(_, "EmployeeID") <> null and Record.Field(_, "EmployeeID") <> ""),
    Typed = Table.TransformColumnTypes(NoBlank, {{"EmployeeID", type text}, {"EmployeeName", type text}, {"Craft", type text}, {"Level", type text}, {"Area", type text}, {"DefaultShift", type text}, {"ContractType", type text}, {"EmploymentStatus", type text}})
in
    Typed

مصادر أوامر العمل (CSV)

WorkOrders · أوامر العمل23 عمود
Month / MonthSort
شهر الإنجاز الفعلي، والمفتوح يصير Open.
Train
من Area: Area A ← Train A، والباقي Common / Utilities.
Open age / OpenAgeSort
عمر الأمر المفتوح: 0-7، 8-30، 31-90، 91-180، 180+ يوم.
Crew
SDMECHPAP ← Shutdown crew، والباقي Routine crew.
let
    Source = Csv.Document(File.Contents("C:\\Users\\rawab\\OneDrive\\Desktop\\معادن - روابي\\01_WorkOrders\\1_Model\\Fact_WorkOrders.csv"), [Delimiter=",", Encoding=65001, QuoteStyle=QuoteStyle.Csv]),
    Headers = Table.PromoteHeaders(Source, [PromoteAllScalars=true]),
    Kept = Table.SelectColumns(Headers, {"WorkOrderKey", "AssetKey", "WorkCenterKey", "StatusKey", "PriorityKey", "TypeKey", "Area", "WODescription", "ActComp", "PlannedMH", "ActualMH", "OnTime_N", "Open_N", "Done_N", "Emergency_N", "PM_N", "AgeDaysOpen"}),
    Typed = Table.TransformColumnTypes(Kept, {{"WorkOrderKey", type text}, {"AssetKey", type text}, {"WorkCenterKey", type text}, {"StatusKey", type text}, {"PriorityKey", type text}, {"TypeKey", type text}, {"Area", type text}, {"WODescription", type text}, {"ActComp", type date}, {"PlannedMH", type number}, {"ActualMH", type number}, {"OnTime_N", Int64.Type}, {"Open_N", Int64.Type}, {"Done_N", Int64.Type}, {"Emergency_N", Int64.Type}, {"PM_N", Int64.Type}, {"AgeDaysOpen", type number}}),
    D1 = Table.AddColumn(Typed, "Month", each if [ActComp] = null then "Open" else Date.ToText([ActComp], "MMM yy"), type text),
    D2 = Table.AddColumn(D1, "MonthSort", each if [ActComp] = null then 999999 else Date.Year([ActComp]) * 100 + Date.Month([ActComp]), Int64.Type),
    D3 = Table.AddColumn(D2, "Train", each if [Area] = null or [Area] = "" then "No area" else if Text.StartsWith([Area], "Area A") then "Train A" else if Text.StartsWith([Area], "Area B") then "Train B" else if Text.StartsWith([Area], "Area C") then "Train C" else "Common / Utilities", type text),
    D4 = Table.AddColumn(D3, "Open age", each if [Open_N] <> 1 then "Done" else if [AgeDaysOpen] = null then "Unknown" else if [AgeDaysOpen] <= 7 then "0-7 d" else if [AgeDaysOpen] <= 30 then "8-30 d" else if [AgeDaysOpen] <= 90 then "31-90 d" else if [AgeDaysOpen] <= 180 then "91-180 d" else "180+ d", type text),
    D5 = Table.AddColumn(D4, "OpenAgeSort", each if [Open age] = "0-7 d" then 1 else if [Open age] = "8-30 d" then 2 else if [Open age] = "31-90 d" then 3 else if [Open age] = "91-180 d" then 4 else if [Open age] = "180+ d" then 5 else 9, Int64.Type),
    D6 = Table.AddColumn(D5, "Crew", each if [WorkCenterKey] = "SDMECHPAP" then "Shutdown crew" else "Routine crew", type text)
in
    D6
Assets · المعدات3 عمود
let
    Source = Csv.Document(File.Contents("C:\\Users\\rawab\\OneDrive\\Desktop\\معادن - روابي\\01_WorkOrders\\1_Model\\Dim_Asset.csv"), [Delimiter=",", Encoding=65001, QuoteStyle=QuoteStyle.Csv]),
    Headers = Table.PromoteHeaders(Source, [PromoteAllScalars=true]),
    Kept = Table.SelectColumns(Headers, {"AssetKey", "AssetDescription", "Criticality"}),
    NoDup = Table.Distinct(Kept, {"AssetKey"})
in
    NoDup

جداول مساعدة تنكتب يدويًا

Calendar · تقويم 2026، الأسبوع يبدأ الأحد4 عمود
let
    D0 = #date(2026, 1, 1),
    Days = List.Dates(D0, 365, #duration(1, 0, 0, 0)),
    T = Table.FromList(Days, Splitter.SplitByNothing(), {"Date"}),
    T1 = Table.TransformColumnTypes(T, {{"Date", type date}}),
    T2 = Table.AddColumn(T1, "Day", each Date.ToText([Date], "ddd"), type text),
    T3 = Table.AddColumn(T2, "DaySort", each Date.DayOfWeek([Date], Day.Sunday), Int64.Type),
    T4 = Table.AddColumn(T3, "Week start", each Date.StartOfWeek([Date], Day.Sunday), type date)
in
    T4
Area · قائمة المناطق بترتيبها2 عمود
let
    S = #table(type table [Area = text, AreaSort = Int64.Type], {{"Train A", 1}, {"Train B", 2}, {"Train C", 3}, {"Common Area", 4}, {"Cooling Tower", 5}})
in
    S
Period · Day / Week / Month لصفحة الحضور2 عمود
let
    S = #table(type table [Period = text, PeriodSort = Int64.Type], {{"Day", 1}, {"Week", 2}, {"Month", 3}})
in
    S
Pick date · تواريخ الحضور للاختيار (بدون علاقة)1 عمود
let
    D = List.Distinct(List.Transform(Attendance[Date], each Date.From(_))),
    T = Table.FromList(List.Sort(D), Splitter.SplitByNothing(), {"Date"}),
    Typed = Table.TransformColumnTypes(T, {{"Date", type date}})
in
    Typed
Meeting date · تواريخ الاجتماع للاختيار (بدون علاقة)1 عمود
let
    D = List.Distinct(List.Transform(Production_Daily[Date], each Date.From(_))),
    T = Table.FromList(List.Sort(D), Splitter.SplitByNothing(), {"Date"}),
    Typed = Table.TransformColumnTypes(T, {{"Date", type date}})
in
    Typed
_Measures · جدول فاضي يجمع المقاييس0 عمود

هذا الجدول ما له بيانات. سويه بـ Enter data ← اسمه _Measures ← Load، وبعد ما تضيفين أول مقياس احذفي عموده الفاضي.

let Source = #table({"_"}, {{1}}) in Source
  1. انقلي الملفات لـ OneDrive القسم وخذي روابطها
    من Excel Desktop: File ← Info ← Copy path، وامسحي ?web=1 من آخر الرابط.
  2. سوي الجداول الثمانية من Daily_Inputs
    بنفس الأسماء: HEMAYA_Log، Spares_Register، Safety_Daily، LLF_Log، Production_Daily، Activities، Concerns، CM_Alerts.
  3. سوي Attendance و Employees
    من ملف الحضور. انتبهي: إذا بنيتي ملف الحضور الجديد، الأعمدة تتغير (شوفي الملاحظات الصريحة تحت).
  4. سوي WorkOrders و Assets من ملفات CSV
  5. سوي الجداول المساعدة الست
    Calendar، Area، Period، Pick date، Meeting date، و _Measures. أول أربعة كودها كامل ما يحتاج ملف.
  6. Close & Apply وتأكدي ما فيه أخطاء
    لو طلع Errors اضغطي عليها: غالبًا اسم عمود مختلف أو تاريخ مكتوب كنص.

المرحلة 2

النموذج والعلاقات

العلاقات

Model view ← اسحبي العمود من جدول الأحداث إلى جدول الوصف. كلها Many to one واتجاه فلترة Single.

من (الكثير)إلى (الواحد)ليش
HEMAYA_Log[Area]Area[Area]فلتر المنطقة يشتغل على كل الصفحات
Spares_Register[Area]Area[Area]فلتر المنطقة يشتغل على كل الصفحات
Safety_Daily[Area]Area[Area]فلتر المنطقة يشتغل على كل الصفحات
LLF_Log[Area]Area[Area]فلتر المنطقة يشتغل على كل الصفحات
Production_Daily[Area]Area[Area]فلتر المنطقة يشتغل على كل الصفحات
Activities[Area]Area[Area]فلتر المنطقة يشتغل على كل الصفحات
Concerns[Area]Area[Area]فلتر المنطقة يشتغل على كل الصفحات
CM_Alerts[Area]Area[Area]فلتر المنطقة يشتغل على كل الصفحات
Attendance[Date]Calendar[Date]محور التاريخ في رسم الحضور
Attendance[EmployeeID]Employees[EmployeeID]بيانات الموظف
WorkOrders[AssetKey]Assets[AssetKey]وصف المعدة

Pick date و Meeting date بدون علاقات، وهذا مقصود. المقاييس تقرأ التاريخ المختار منهم وتحسب نافذة (يوم، أسبوع، شهر، أو أمس). لو ربطتيهم، الفلتر بيقص البيانات قبل ما المقياس يحسب.

Sort by column وإخفاء الأعمدة المساعدة

اضغطي العمود في Data view ← Column tools ← Sort by column. وبعدها كليك يمين على عمود الترتيب ← Hide in report view.

العموديترتب حسب
Area[Area]AreaSort
Period[Period]PeriodSort
Calendar[Day]DaySort
HEMAYA_Log[Severity]SeveritySort
HEMAYA_Log[Age bucket]AgeSort
HEMAYA_Log[Month]MonthSort
Spares_Register[Stock health]HealthSort
Attendance[Presence]PresenceSort
WorkOrders[Month]MonthSort
WorkOrders[Open age]OpenAgeSort

الأعمدة المخفية في الملف الأصلي: Area[AreaSort] Period[PeriodSort] Calendar[DaySort] HEMAYA_Log[Source] HEMAYA_Log[Overdue] HEMAYA_Log[Closed on time] HEMAYA_Log[AgeSort] HEMAYA_Log[MonthSort] HEMAYA_Log[SeveritySort] HEMAYA_Log[IsClosed] Spares_Register[Source] Spares_Register[HealthSort] Spares_Register[Return overdue] Attendance[PresenceSort] WorkOrders[MonthSort] WorkOrders[OpenAgeSort]

  1. اربطي العلاقات كلها
    11 علاقة، وتأكدي إن كل خط عليه 1 و *.
  2. اضبطي Sort by column لكل عمود في الجدول
    بدونها الشهور تترتب أبجديًا (Apr قبل Jan) والشدة (Critical بعد High).
  3. أخفي الأعمدة المساعدة
    كذا قائمة الحقول تبقى نظيفة لأي أحد يفتح الملف.

المرحلة 3

المقاييس

كل المقاييس في جدول _Measures، مقسمة بخمس مجلدات. لكل مقياس: اضغطي New measure ← الصقي ← حطي التنسيق (Format) ← Display folder.

قاعدةليش
… + 0 في آخر مقاييس العدعشان البطاقة تكتب 0 بدل (Blank)
مقاييس Sub …نص صغير تحت الرقم الكبير يشرح معناه (مثل "Target 80% · gap")
مقاييس SVGترسم شارة أو شريط داخل الجدول. لازم Data category = Image URL (Measure tools ← Data category)
أسماء تبدأ بحرفH حماية · S قطع الغيار · A الحضور · W أوامر العمل · D الاجتماع، عشان تلقينها بسرعة
01 HEMAYA · حماية: العدد، المفتوح، المتأخر، نسبة الإغلاق، والشارات المرسومة SVG.28 مقياس
H TotalFormat: #,0
COUNTROWS ( HEMAYA_Log ) + 0
H OpenFormat: #,0
CALCULATE ( COUNTROWS ( HEMAYA_Log ), HEMAYA_Log[Status] <> "Closed" ) + 0
H ClosedFormat: #,0
CALCULATE ( COUNTROWS ( HEMAYA_Log ), HEMAYA_Log[Status] = "Closed" ) + 0
H OverdueFormat: #,0
CALCULATE ( COUNTROWS ( HEMAYA_Log ), HEMAYA_Log[Overdue] = 1 ) + 0
H Closure %Format: 0%
DIVIDE ( [H Closed], [H Total] )
H On-time %Format: 0%
DIVIDE ( CALCULATE ( COUNTROWS ( HEMAYA_Log ), HEMAYA_Log[Closed on time] = 1 ), [H Closed] )
H Avg days to closeFormat: 0.0
CALCULATE ( AVERAGE ( HEMAYA_Log[Days open] ), HEMAYA_Log[Status] = "Closed" )
H IncidentsFormat: #,0
CALCULATE ( COUNTROWS ( HEMAYA_Log ), HEMAYA_Log[Type] = "Incident" ) + 0
H Near missesFormat: #,0
CALCULATE ( COUNTROWS ( HEMAYA_Log ), HEMAYA_Log[Type] = "Near miss" ) + 0
H Unsafe actsFormat: #,0
CALCULATE ( COUNTROWS ( HEMAYA_Log ), HEMAYA_Log[Type] = "Unsafe act" ) + 0
H Unsafe conditionsFormat: #,0
CALCULATE ( COUNTROWS ( HEMAYA_Log ), HEMAYA_Log[Type] = "Unsafe condition" ) + 0
H Good practiceFormat: #,0
CALCULATE ( COUNTROWS ( HEMAYA_Log ), HEMAYA_Log[Type] = "Good practice" ) + 0
H Critical openFormat: #,0
CALCULATE ( COUNTROWS ( HEMAYA_Log ), HEMAYA_Log[Status] <> "Closed", HEMAYA_Log[Severity] IN { "Critical", "High" } ) + 0
H Days since incidentFormat: #,0
VAR ref = CALCULATE ( MAX ( HEMAYA_Log[Reported] ), ALL ( HEMAYA_Log ) )
VAR last = CALCULATE ( MAX ( HEMAYA_Log[Reported] ), ALL ( HEMAYA_Log ), HEMAYA_Log[Type] = "Incident" )
RETURN IF ( ISBLANK ( last ), BLANK (), INT ( ref - last ) )
H Assigned MechFormat: #,0
CALCULATE ( COUNTROWS ( HEMAYA_Log ), HEMAYA_Log[Owner dept] = "Mechanical" ) + 0
H Assigned Mech openFormat: #,0
CALCULATE ( COUNTROWS ( HEMAYA_Log ), HEMAYA_Log[Owner dept] = "Mechanical", HEMAYA_Log[Status] <> "Closed" ) + 0
H Assigned Mech overdueFormat: #,0
CALCULATE ( COUNTROWS ( HEMAYA_Log ), HEMAYA_Log[Owner dept] = "Mechanical", HEMAYA_Log[Overdue] = 1 ) + 0
H Raised MechFormat: #,0
CALCULATE ( COUNTROWS ( HEMAYA_Log ), HEMAYA_Log[Raised dept] = "Mechanical" ) + 0
H Raised Mech monthFormat: #,0
VAR ref = CALCULATE ( MAX ( HEMAYA_Log[Reported] ), ALL ( HEMAYA_Log ) )
RETURN CALCULATE ( COUNTROWS ( HEMAYA_Log ), HEMAYA_Log[Raised dept] = "Mechanical", HEMAYA_Log[Reported] >= DATE ( YEAR ( ref ), MONTH ( ref ), 1 ) ) + 0
H Sub assigned
"Open " & FORMAT ( [H Assigned Mech open], "#,0" ) & " · overdue " & FORMAT ( [H Assigned Mech overdue], "#,0" )
H Sub raised
"This month " & FORMAT ( [H Raised Mech month], "#,0" ) & " · count only"
H Sub closure
"Closed " & FORMAT ( [H Closed], "#,0" ) & " of " & FORMAT ( [H Total], "#,0" )
H Sub overdue
"Past target date, still open"
H Sub avg
"On time " & FORMAT ( [H On-time %], "0%" )
H Sub incidents
"Near misses " & FORMAT ( [H Near misses], "#,0" )
H Status pill · Image URL
IF ( NOT HASONEVALUE ( HEMAYA_Log[ID] ), BLANK (),
VAR s = SELECTEDVALUE ( HEMAYA_Log[Status] )
VAR od = MAX ( HEMAYA_Log[Overdue] )
VAR st = SWITCH ( TRUE (), s = "Closed", "CLOSED", od = 1, "OVERDUE", s = "In progress", "IN PROGRESS", "OPEN" )
VAR bg = SWITCH ( st, "CLOSED", "#E3F1E8", "OVERDUE", "#FBE7E5", "IN PROGRESS", "#FBF0D9", "#F1EACB" )
VAR fg = SWITCH ( st, "CLOSED", "#007A3D", "OVERDUE", "#8A340F", "IN PROGRESS", "#A35009", "#343631" )
VAR ic = SWITCH ( st, "CLOSED", "<path d='M8 12 L11 15 L16 9' stroke='" & fg & "' stroke-width='2.2' fill='none' stroke-linecap='round' stroke-linejoin='round'/>", "OVERDUE", "<path d='M12 7 L17 16 L7 16 Z' fill='" & fg & "'/>", "IN PROGRESS", "<circle cx='12' cy='12' r='4.5' fill='none' stroke='" & fg & "' stroke-width='2'/>", "<circle cx='12' cy='12' r='3' fill='" & fg & "'/>" )
VAR svg = "<svg xmlns='http://www.w3.org/2000/svg' width='112' height='24' viewBox='0 0 112 24'>" & "<rect x='0.5' y='0.5' width='111' height='23' rx='11.5' fill='" & bg & "' stroke='" & fg & "' stroke-opacity='0.35'/>" & ic & "<text x='24' y='16' font-family='Segoe UI' font-size='10.5' font-weight='600' fill='" & fg & "'>" & st & "</text></svg>"
RETURN "data:image/svg+xml;utf8," & SUBSTITUTE ( svg, "#", "%23" ) )
H Age meter · Image URL
IF ( NOT HASONEVALUE ( HEMAYA_Log[ID] ), BLANK (),
VAR d = INT ( MAX ( HEMAYA_Log[Days open] ) )
VAR done = MAX ( HEMAYA_Log[IsClosed] )
VAR sg = SWITCH ( TRUE (), d <= 7, 1, d <= 30, 2, d <= 60, 3, 4 )
VAR col = IF ( done = 1, "#BDBAB5", SWITCH ( sg, 1, "#6B634B", 2, "#6B634B", 3, "#C76210", "#8A340F" ) )
VAR off = "#E0DEDB"
VAR c = "<rect y='6' width='20' height='10' rx='2' "
VAR svg = "<svg xmlns='http://www.w3.org/2000/svg' width='136' height='22' viewBox='0 0 136 22'>" & c & "x='0' fill='" & col & "'/>" & c & "x='22' fill='" & IF ( sg >= 2, col, off ) & "'/>" & c & "x='44' fill='" & IF ( sg >= 3, col, off ) & "'/>" & c & "x='66' fill='" & IF ( sg >= 4, col, off ) & "'/>" & "<text x='94' y='16' font-family='Segoe UI' font-size='11' font-weight='600' fill='" & IF ( done = 0 && sg >= 3, IF ( sg = 3, "#A35009", "#8A340F" ), "#343631" ) & "'>" & d & " d</text></svg>"
RETURN "data:image/svg+xml;utf8," & SUBSTITUTE ( svg, "#", "%23" ) )
H Days ring · Image URL
VAR d = [H Days since incident]
VAR arc = INT ( MIN ( DIVIDE ( d, 365 ), 1 ) * 163 )
VAR svg = "<svg xmlns='http://www.w3.org/2000/svg' width='64' height='64' viewBox='0 0 64 64'>" & "<circle cx='32' cy='32' r='26' fill='none' stroke='#E0DEDB' stroke-width='6'/>" & "<circle cx='32' cy='32' r='26' fill='none' stroke='#B8A567' stroke-width='6' stroke-linecap='round' stroke-dasharray='" & arc & " 164' transform='rotate(-90 32 32)'/>" & "<text x='32' y='37' text-anchor='middle' font-family='Segoe UI' font-size='15' font-weight='700' fill='#343631'>" & d & "</text></svg>"
RETURN IF ( ISBLANK ( d ), BLANK (), "data:image/svg+xml;utf8," & SUBSTITUTE ( svg, "#", "%23" ) )
02 Spares · قطع الغيار: الصحة، النافد، الحرج، القيمة، وشريط المخزون SVG.15 مقياس
S ItemsFormat: #,0
COUNTROWS ( Spares_Register ) + 0
S Out of stockFormat: #,0
CALCULATE ( COUNTROWS ( Spares_Register ), Spares_Register[Stock health] = "Out of stock" ) + 0
S Below minimumFormat: #,0
CALCULATE ( COUNTROWS ( Spares_Register ), Spares_Register[Stock health] IN { "Below minimum", "Reorder now" } ) + 0
S Critical at riskFormat: #,0
CALCULATE ( COUNTROWS ( Spares_Register ), Spares_Register[Criticality] = "A", Spares_Register[Stock health] IN { "Out of stock", "Below minimum", "Reorder now" } ) + 0
S Under repairFormat: #,0
CALCULATE ( COUNTROWS ( Spares_Register ), Spares_Register[Status] = "Under repair (CWS)" ) + 0
S On orderFormat: #,0
CALCULATE ( COUNTROWS ( Spares_Register ), Spares_Register[Status] = "On order" ) + 0
S Return overdueFormat: #,0
CALCULATE ( COUNTROWS ( Spares_Register ), Spares_Register[Return overdue] = 1 ) + 0
S Healthy %Format: 0%
DIVIDE ( CALCULATE ( COUNTROWS ( Spares_Register ), Spares_Register[Stock health] = "Healthy" ), [S Items] )
S Stock valueFormat: #,0.00
DIVIDE ( SUM ( Spares_Register[Stock value SAR] ), 1000000 ) + 0
S Slow movingFormat: #,0
CALCULATE ( COUNTROWS ( Spares_Register ), Spares_Register[Days since movement] > 180 ) + 0
S QtyFormat: #,0
SUM ( Spares_Register[Qty on hand] ) + 0
S Sub critical
"Criticality A spares out or below minimum"
S Sub repair
"Return overdue " & FORMAT ( [S Return overdue], "#,0" )
S Sub value
"Slow moving over 180 days " & FORMAT ( [S Slow moving], "#,0" )
S Stock bar · Image URL
IF ( NOT HASONEVALUE ( Spares_Register[Part No] ), BLANK (),
VAR q = SUM ( Spares_Register[Qty on hand] )
VAR mn = MAX ( Spares_Register[Min] )
VAR rp = MAX ( Spares_Register[Reorder point] )
VAR mx = MAX ( Spares_Register[Max] )
VAR sc = MAX ( MAX ( mx, q ) * 1.15, 1 )
VAR w = 140
VAR xn = INT ( mn / sc * w )
VAR xr = INT ( rp / sc * w )
VAR xm = INT ( mx / sc * w )
VAR xq = INT ( MIN ( q, sc ) / sc * w )
VAR st = SWITCH ( TRUE (), q <= 0, "OUT", q < mn, "LOW", q <= rp, "ROP", q > mx, "EXCESS", "OK" )
VAR col = SWITCH ( st, "OUT", "#8A340F", "LOW", "#8A340F", "ROP", "#C76210", "EXCESS", "#5F5E5B", "#007A3D" )
VAR tx = IF ( st = "ROP", "#A35009", IF ( st = "EXCESS", "#5F5E5B", col ) )
VAR svg = "<svg xmlns='http://www.w3.org/2000/svg' width='196' height='24' viewBox='0 0 196 24'>" & "<rect x='0' y='7' width='" & w & "' height='10' fill='#F7F3E9'/>" & "<rect x='0' y='7' width='" & xn & "' height='10' fill='#FBE7E5'/>" & "<rect x='" & xn & "' y='7' width='" & MAX ( xr - xn, 0 ) & "' height='10' fill='#FBF0D9'/>" & "<rect x='" & xr & "' y='7' width='" & MAX ( xm - xr, 0 ) & "' height='10' fill='#E3F1E8'/>" & "<rect x='0' y='10' width='" & xq & "' height='4' fill='" & col & "'/>" & "<rect x='" & xr & "' y='5' width='1' height='14' fill='#5E6259'/>" & "<path d='M" & xq & " 7 L" & ( xq - 4 ) & " 1 L" & ( xq + 4 ) & " 1 Z' fill='#343631'/>" & IF ( st = "OUT", "<path d='M146 7 L154 15 M154 7 L146 15' stroke='#8A340F' stroke-width='2.2'/>", "" ) & "<text x='" & IF ( st = "OUT", 160, 148 ) & "' y='16' font-family='Segoe UI' font-size='11' font-weight='600' fill='" & tx & "'>" & INT ( q ) & "</text></svg>"
RETURN "data:image/svg+xml;utf8," & SUBSTITUTE ( svg, "#", "%23" ) )
03 Attendance · الحضور: نافذة التاريخ (يوم/أسبوع/شهر) وكل الأرقام محسوبة داخلها.25 مقياس
Sel dateFormat: ddd dd MMM yyyy
IF ( ISFILTERED ( 'Pick date'[Date] ), MAX ( 'Pick date'[Date] ), CALCULATE ( MAX ( Attendance[Date] ), ALL ( Attendance ) ) )
Sel period
SELECTEDVALUE ( Period[Period], "Day" )
Win startFormat: dd MMM yyyy
VAR d = [Sel date]
RETURN SWITCH ( [Sel period], "Week", d - WEEKDAY ( d, 1 ) + 1, "Month", DATE ( YEAR ( d ), MONTH ( d ), 1 ), d )
Win endFormat: dd MMM yyyy
VAR d = [Sel date]
RETURN SWITCH ( [Sel period], "Week", d - WEEKDAY ( d, 1 ) + 7, "Month", EOMONTH ( d, 0 ), d )
A RecordsFormat: #,0
VAR s = [Win start]
VAR e = [Win end]
RETURN CALCULATE ( COUNTROWS ( Attendance ), Attendance[Date] >= s, Attendance[Date] <= e ) + 0
A On siteFormat: #,0
VAR s = [Win start]
VAR e = [Win end]
RETURN CALCULATE ( SUM ( Attendance[On Site] ), Attendance[Date] >= s, Attendance[Date] <= e ) + 0
A Day shiftFormat: #,0
VAR s = [Win start]
VAR e = [Win end]
RETURN CALCULATE ( CALCULATE ( SUM ( Attendance[On Site] ), Attendance[Shift] = "Day" ), Attendance[Date] >= s, Attendance[Date] <= e ) + 0
A Night shiftFormat: #,0
VAR s = [Win start]
VAR e = [Win end]
RETURN CALCULATE ( CALCULATE ( SUM ( Attendance[On Site] ), Attendance[Shift] = "Night" ), Attendance[Date] >= s, Attendance[Date] <= e ) + 0
A AbsentFormat: #,0
VAR s = [Win start]
VAR e = [Win end]
RETURN CALCULATE ( CALCULATE ( COUNTROWS ( Attendance ), Attendance[Presence] IN { "Absent", "Sick leave" } ), Attendance[Date] >= s, Attendance[Date] <= e ) + 0
A LeaveFormat: #,0
VAR s = [Win start]
VAR e = [Win end]
RETURN CALCULATE ( CALCULATE ( COUNTROWS ( Attendance ), Attendance[Presence] IN { "Vacation", "Day off" } ), Attendance[Date] >= s, Attendance[Date] <= e ) + 0
A PeopleFormat: #,0
VAR s = [Win start]
VAR e = [Win end]
RETURN CALCULATE ( DISTINCTCOUNT ( Attendance[EmployeeID] ), Attendance[Date] >= s, Attendance[Date] <= e ) + 0
A Active headcountFormat: #,0
CALCULATE ( COUNTROWS ( Employees ), Employees[EmploymentStatus] = "Active" ) + 0
A Days loggedFormat: #,0
VAR s = [Win start]
VAR e = [Win end]
RETURN CALCULATE ( DISTINCTCOUNT ( Attendance[Date] ), Attendance[Date] >= s, Attendance[Date] <= e ) + 0
A Attendance %Format: 0%
DIVIDE ( [A On site], [A Records] )
A Absence %Format: 0.0%
DIVIDE ( [A Absent], [A Records] )
A Coverage %Format: 0%
DIVIDE ( [A Records], [A Active headcount] * MAX ( 1, [A Days logged] ) )
A Avg on site per dayFormat: #,0
DIVIDE ( [A On site], [A Days logged] )
A In windowFormat: 0
VAR d = MAX ( Attendance[Date] ) RETURN IF ( d >= [Win start] && d <= [Win end], 1, 0 )
A On site in windowFormat: #,0
VAR d = MAX ( Calendar[Date] ) RETURN IF ( d >= [Win start] && d <= [Win end], SUM ( Attendance[On Site] ) )
A On site rest of monthFormat: #,0
VAR d = MAX ( Calendar[Date] )
VAR sd = [Sel date]
RETURN IF ( ( d < [Win start] || d > [Win end] ) && d >= DATE ( YEAR ( sd ), MONTH ( sd ), 1 ) && d <= EOMONTH ( sd, 0 ), SUM ( Attendance[On Site] ) )
A Window label
[Sel period] & " · " & IF ( [Win start] = [Win end], FORMAT ( [Win start], "ddd dd MMM yyyy" ), FORMAT ( [Win start], "dd MMM" ) & " to " & FORMAT ( [Win end], "dd MMM yyyy" ) )
A Sub on site
"Day " & FORMAT ( [A Day shift], "#,0" ) & " · Night " & FORMAT ( [A Night shift], "#,0" )
A Sub coverage
"Logged " & FORMAT ( [A Records], "#,0" ) & " of " & FORMAT ( [A Active headcount] * MAX ( 1, [A Days logged] ), "#,0" )
A Sub absent
FORMAT ( [A Absent], "#,0" ) & " absent or sick"
A Sub people
"Across " & FORMAT ( [A Days logged], "#,0" ) & " day(s)"
04 Work orders · أوامر العمل: الوقائي، الطوارئ، الالتزام، الساعات، والمفتوح.17 مقياس
W TotalFormat: #,0
COUNTROWS ( WorkOrders ) + 0
W PM %Format: 0.0%
DIVIDE ( SUM ( WorkOrders[PM_N] ), [W Total] )
W Emergency %Format: 0.0%
DIVIDE ( SUM ( WorkOrders[Emergency_N] ), [W Total] )
W Schedule compliance %Format: 0.0%
DIVIDE ( SUM ( WorkOrders[OnTime_N] ), SUM ( WorkOrders[Done_N] ) )
W MH variance %Format: +0.0%;-0.0%;0.0%
DIVIDE ( SUM ( WorkOrders[ActualMH] ) - SUM ( WorkOrders[PlannedMH] ), SUM ( WorkOrders[PlannedMH] ) )
W OpenFormat: #,0
SUM ( WorkOrders[Open_N] ) + 0
W Backlog MHFormat: #,0
CALCULATE ( SUM ( WorkOrders[PlannedMH] ), WorkOrders[Open_N] = 1 ) + 0
W EmergenciesFormat: #,0
SUM ( WorkOrders[Emergency_N] ) + 0
W PMFormat: #,0
SUM ( WorkOrders[PM_N] ) + 0
W CMFormat: #,0
[W Total] - [W PM]
W PM targetFormat: 0%
0.8
W SC targetFormat: 0%
0.85
W Sub PM
"Target 80% · gap " & FORMAT ( [W PM %] - 0.8, "+0.0%;-0.0%" )
W Sub EM
"Cap 5% · " & FORMAT ( [W Emergencies], "#,0" ) & " orders"
W Sub SC
"Target 85% · ±1 day tolerance"
W Sub MH
"Allowed ±10%"
W Sub total
FORMAT ( [W Open], "#,0" ) & " open · backlog " & FORMAT ( [W Backlog MH], "#,0" ) & " h"
05 Daily meeting · الاجتماع: تاريخ الاجتماع، أرقام أمس، والمخاوف والتنبيهات.24 مقياس
D Meeting dateFormat: ddd dd MMM yyyy
IF ( ISFILTERED ( 'Meeting date'[Date] ), MAX ( 'Meeting date'[Date] ), CALCULATE ( MAX ( Production_Daily[Date] ), ALL ( Production_Daily ) ) )
D Actual yesterdayFormat: #,0
VAR d = [D Meeting date]
RETURN CALCULATE ( SUM ( Production_Daily[Actual MT] ), Production_Daily[Date] = d - 1 ) + 0
D Target yesterdayFormat: #,0
VAR d = [D Meeting date]
RETURN CALCULATE ( SUM ( Production_Daily[Target MT] ), Production_Daily[Date] = d - 1 ) + 0
D Production %Format: 0%
DIVIDE ( [D Actual yesterday], [D Target yesterday] )
D Downtime yesterdayFormat: 0.0
VAR d = [D Meeting date]
RETURN CALCULATE ( SUM ( Production_Daily[Downtime hrs] ), Production_Daily[Date] = d - 1 ) + 0
D Unsafe todayFormat: #,0
VAR d = [D Meeting date]
RETURN CALCULATE ( SUM ( Safety_Daily[Unsafe conditions] ) + SUM ( Safety_Daily[Unsafe acts] ), Safety_Daily[Date] = d ) + 0
D Incidents todayFormat: #,0
VAR d = [D Meeting date] RETURN CALCULATE ( SUM ( Safety_Daily[Incidents] ), Safety_Daily[Date] = d ) + 0
D HEMAYA openFormat: #,0
[H Open]
D Concerns openFormat: #,0
CALCULATE ( COUNTROWS ( Concerns ), Concerns[Status] <> "Closed" ) + 0
D Concerns overdueFormat: #,0
VAR d = [D Meeting date]
RETURN CALCULATE ( COUNTROWS ( Concerns ), Concerns[Status] <> "Closed", Concerns[Due] < d ) + 0
D CM openFormat: #,0
CALCULATE ( COUNTROWS ( CM_Alerts ), CM_Alerts[Status] <> "Closed" ) + 0
D CM dangerFormat: #,0
CALCULATE ( COUNTROWS ( CM_Alerts ), CM_Alerts[Status] <> "Closed", CM_Alerts[Level] = "Danger" ) + 0
D LLF openFormat: #,0
CALCULATE ( COUNTROWS ( LLF_Log ), LLF_Log[Status] = "Open" ) + 0
D Is todayFormat: 0
VAR d = MAX ( Activities[Date] ) RETURN IF ( d = [D Meeting date], 1, 0 )
D Is yesterdayFormat: 0
VAR d = MAX ( Activities[Date] ) RETURN IF ( d = [D Meeting date] - 1, 1, 0 )
D Prod trend actualFormat: #,0
VAR d = MAX ( 'Meeting date'[Date] )
RETURN CALCULATE ( SUM ( Production_Daily[Actual MT] ), Production_Daily[Date] = d )
D Prod trend targetFormat: #,0
VAR d = MAX ( 'Meeting date'[Date] )
RETURN CALCULATE ( SUM ( Production_Daily[Target MT] ), Production_Daily[Date] = d )
D Downtime trendFormat: 0.0
VAR d = MAX ( 'Meeting date'[Date] )
RETURN CALCULATE ( SUM ( Production_Daily[Downtime hrs] ), Production_Daily[Date] = d )
D Sub production
"Target " & FORMAT ( [D Target yesterday], "#,0" ) & " MT · " & FORMAT ( [D Production %], "0%" )
D Sub safety
FORMAT ( [D Incidents today], "#,0" ) & " incidents today"
D Sub concerns
FORMAT ( [D Concerns overdue], "#,0" ) & " past due date"
D Sub cm
FORMAT ( [D CM danger], "#,0" ) & " at danger level"
D Title
"Daily meeting · " & FORMAT ( [D Meeting date], "dddd dd MMMM yyyy" )
Data note
"Sample rows marked DUMMY: HEMAYA " & FORMAT ( CALCULATE ( COUNTROWS ( HEMAYA_Log ), HEMAYA_Log[Source] = "DUMMY sample" ), "#,0" ) & " · spares " & FORMAT ( CALCULATE ( COUNTROWS ( Spares_Register ), Spares_Register[Source] = "DUMMY sample" ), "#,0" )
  1. سوي جدول _Measures
    Enter data ← الاسم _Measures ← Load.
  2. أضيفي مجلد 01 HEMAYA واختبريه
    حطي [H Total] في Card وقارنيه بعدد صفوف HEMAYA_Log في Excel. ليش أول: لو الرقم الأول صح، الباقي مبني على نفس الجدول.
  3. أضيفي باقي المجلدات بالترتيب
    02 Spares ← 03 Attendance ← 04 Work orders ← 05 Daily meeting. بعض المقاييس تنادي غيرها، فالترتيب يمنع الأخطاء.
  4. اضبطي Data category = Image URL للمقاييس الأربعة
    H Status pill، H Age meter، H Days ring، S Stock bar. بدونها يطلع كود نصي بدل الرسمة.

المرحلة 4

الثيم والخلفيات والتنقل

هذي المرحلة تسوينها مرة وحدة على صفحة Home، وبعدها تنسخينها للباقي.

إعدادات الصفحة

الثيم
View ← Themes ← Browse for themes ← Hub_Theme.json
المقاس
Format page ← Canvas settings ← Type: Custom ← 1280 × 720
خلفية الصفحة
#F7F3E9 Bone، شفافية 0%
Wallpaper
#E0DEDB Moonstone
الخط
الأرقام الكبيرة DIN Next LT Pro، وكل النصوص Segoe UI و Segoe UI Semibold

الخلفية المرسومة

  1. Insert ← Image ← bg_home.png.
  2. Format ← General ← Properties: X 0 · Y 0 · Width 1280 · Height 720.
  3. Arrange ← Send to back، وبعدها View ← Lock objects وقت ترتيب الباقي عشان ما تتحرك.
خلفية الصفحة الرئيسية

أزرار التنقل (الشريط الجانبي)

6 أزرار شفافة فوق الأيقونات المرسومة. Insert ← Buttons ← Blank، ولكل زر:

الزرXYW × HAction
107276 × 64Page navigation ← Home
2014676 × 64Page navigation ← Daily meeting
3022076 × 64Page navigation ← HEMAYA
4029476 × 64Page navigation ← Attendance
5036876 × 64Page navigation ← Work orders
6044276 × 64Page navigation ← Spare parts

في Format للزر: Style ← Icon off، Text off، Fill off، Border off. وAction ← Type: Page navigation ← Destination. ليش شفافة: الأيقونة والتمييز للصفحة الحالية مرسومين في الخلفية، والزر بس يستقبل الضغطة.

الستايلات الموحدة (استخدمي Format painter)

نسّقي أول visual من كل نوع بالقيم هذي، وبعدها Home ← Format painter وانسخي التنسيق للباقي.

النوعالتنسيق
كل visualBackground off · Border off · Shadow off · Title off · Visual header off · Padding 0
Card: الرقم الكبيرCallout: DIN Next LT Pro 22 (Home: 28) · #343631 · Category label off
Card: السطر الصغيرSegoe UI 7.5 (Home: 8) · #6B6E66 · Word wrap on
Table و MatrixColumn headers: Segoe UI Semibold 8 · نص #5F5E5B على #F7F3E9 · Outline Bottom only
Values: Segoe UI 8 · #343631 · صفوف متبادلة #FFFFFF و #FBF9F3
Grid: horizontal فقط #E0DEDB · Row padding 4 · Totals off
Matrix حراريCell elements ← Background color ← fx ← Gradient من Bone إلى الذهبي (ألوان الثيم minimum/maximum)
الرسومX axis: Segoe UI 8 #5F5E5B · Y axis off · Gridlines dotted #E0DEDB · Data labels Segoe UI Semibold 8 · Legend Top 8
Slicer: أزرارSlicer settings ← Style: Tile · Orientation horizontal · Segoe UI Semibold 8 · خلفية بيضاء · Frame #E0DEDB · Header off
Slicer: قائمةStyle: Dropdown · Segoe UI Semibold 9 · Frame #B8A567 · Header off
  1. استوردي الثيم واضبطي المقاس 1280×720
  2. حطي خلفية Home وقفليها ورا
  3. سوي أزرار التنقل الست
    بالمواقع في الجدول فوق، وجربيها بـ Ctrl + ضغطة في Desktop.
  4. سوي الصفحات الخمس الباقية بـ Duplicate page
    كليك يمين على Home ← Duplicate. وبعدين غيري صورة الخلفية لكل صفحة، واحذفي visuals الرئيسية منها. الأزرار تبقى بمكانها بالضبط.

المرحلة 5

الصفحات الست

لكل صفحة: الخلفية، والسؤال اللي تجاوبه، وجدول فيه كل visual بمكانه ومقاسه والحقول. الأرقام بالبكسل: Format ← General ← Properties ← Size and position. الترتيب في الجدول من فوق لتحت، مثل ما تبنينها.

الصفحة الرئيسية · Home

وين المشكلة اليوم؟ خمس بطاقات، كل وحدة تفتح صفحتها.

خلفية صفحة الصفحة الرئيسية
#النوعالحقولX, YW × Hالتنسيق
1Card (رقم)[D Title]842, 108400 × 26Segoe UI 10 · #F1EACB
2Card (رقم)[Data note]842, 140400 × 24Segoe UI 8 · #BDBAB5
3Button94, 204222 × 238Page navigation ← Daily meeting
4Button330, 204222 × 238Page navigation ← HEMAYA
5Button566, 204222 × 238Page navigation ← Attendance
6Button803, 204222 × 238Page navigation ← Work orders
7Button1039, 204222 × 238Page navigation ← Spare parts
8Card (رقم)[D Actual yesterday]110, 350190 × 50DIN 28 · #343631
9Card (رقم)[H Open]346, 350190 × 50DIN 28 · #343631
10Card (رقم)[A On site]582, 350190 × 50DIN 28 · #343631
11Card (رقم)[W PM %]819, 350190 × 50DIN 28 · #343631
12Card (رقم)[S Critical at risk]1055, 350190 × 50DIN 28 · #343631
13Card (رقم)[D Sub production]112, 400186 × 30Segoe UI 8 · #6B6E66
14Card (رقم)[H Sub overdue]348, 400186 × 30Segoe UI 8 · #6B6E66
15Card (رقم)[A Sub on site]584, 400186 × 30Segoe UI 8 · #6B6E66
16Card (رقم)[W Sub PM]821, 400186 × 30Segoe UI 8 · #6B6E66
17Card (رقم)[S Sub critical]1057, 400186 × 30Segoe UI 8 · #6B6E66
18TableID Area What happened [H Age meter]108, 504352 × 188ستايل الجدول الموحد · Image 24×140
19TableDescription Area Qty on hand Stock health502, 504352 × 188ستايل الجدول الموحد · Image 22×auto
20Area chartMonth [W PM %]896, 504352 × 188لون #B8A567 · Labels on · Legend off

الاجتماع الصباحي · Daily meeting

إنتاج أمس مقابل الهدف، السلامة، خطة اليوم، المخاوف، ومراقبة الحالة.

خلفية صفحة الاجتماع الصباحي
#النوعالحقولX, YW × Hالتنسيق
1SlicerDate722, 24210 × 30Dropdown · Single select
2SlicerArea944, 22318 × 34Tile أفقي · Multi select
3Card (رقم)[H Assigned Mech]104, 112127 × 38DIN 22 · #8A340F
4Card (رقم)[H Raised Mech]301, 112127 × 38DIN 22 · #343631
5Card (رقم)[D Actual yesterday]498, 112127 × 38DIN 22 · #343631
6Card (رقم)[D Downtime yesterday]695, 112127 × 38DIN 22 · #343631
7Card (رقم)[D Concerns open]892, 112127 × 38DIN 22 · #343631
8Card (رقم)[D CM open]1089, 112127 × 38DIN 22 · #343631
9Card (رقم)[H Sub assigned]104, 150165 × 24Segoe UI 7.5 · #6B6E66
10Card (رقم)[H Sub raised]301, 150165 × 24Segoe UI 7.5 · #6B6E66
11Card (رقم)[D Sub production]498, 150165 × 24Segoe UI 7.5 · #6B6E66
12Card (رقم)[D Sub concerns]892, 150165 × 24Segoe UI 7.5 · #6B6E66
13Card (رقم)[D Sub cm]1089, 150165 × 24Segoe UI 7.5 · #6B6E66
14TableLocation Type What happened Corrective action (how closed) Owner [H Status pill] [H Age meter]108, 240746 × 190ستايل الجدول الموحد · Image 24×140
15Clustered barRaised by [H Total]896, 240352 × 190لون #B8A567 · Labels on · Legend off
16Line & clustered columnDate [D Prod trend actual] [D Prod trend target]108, 504352 × 188لون #B8A567 · Labels off · Legend Top
17TableArea Activity Work order Crew Status502, 504352 × 188ستايل الجدول الموحد · Image 22×auto
18TableArea Concern / highlight Owner Due896, 504352 × 188ستايل الجدول الموحد · Image 22×auto

حماية HEMAYA · HEMAYA

وش انرصد، ووين، وليش، وكيف انقفل، ومتى.

خلفية صفحة حماية HEMAYA
#النوعالحقولX, YW × Hالتنسيق
1SlicerType722, 24210 × 30Dropdown · Multi select
2SlicerArea944, 22318 × 34Tile أفقي · Multi select
3Card (رقم)[H Total]104, 112127 × 38DIN 22 · #343631
4Card (رقم)[H Open]301, 112127 × 38DIN 22 · #343631
5Card (رقم)[H Overdue]498, 112127 × 38DIN 22 · #8A340F
6Card (رقم)[H Closure %]695, 112127 × 38DIN 22 · #343631
7Card (رقم)[H Avg days to close]892, 112127 × 38DIN 22 · #343631
8Card (رقم)[H Days since incident]1089, 112127 × 38DIN 22 · #343631
9Card (رقم)[H Sub closure]104, 150165 × 24Segoe UI 7.5 · #6B6E66
10Card (رقم)[H Sub overdue]498, 150165 × 24Segoe UI 7.5 · #6B6E66
11Card (رقم)[H Sub avg]695, 150165 × 24Segoe UI 7.5 · #6B6E66
12Card (رقم)[H Sub incidents]1089, 150165 × 24Segoe UI 7.5 · #6B6E66
13DonutType [H Total]108, 240352 × 178لون #C76210 · Labels on · Legend Right
14Stacked columnMonth [H Closed] [H Open]502, 240352 × 178لون #007A3D · Labels on · Legend Top
15MatrixArea Severity [H Total]896, 240352 × 178ستايل الجدول الموحد · Image 22×auto
16Clustered barCategory [H Total]108, 492332 × 200لون #5F5E5B · Labels on · Legend off
17Table[H Status pill] Reported Location What happened Root cause (why) Corrective action (how closed) Owner [H Age meter]482, 492766 × 200ستايل الجدول الموحد · Image 24×140

الحضور · Attendance

مين موجود، ووين، وبأي شفت، يوم أو أسبوع أو شهر.

خلفية صفحة الحضور
#النوعالحقولX, YW × Hالتنسيق
1SlicerPeriod622, 22280 × 34Tile أفقي · Single select
2SlicerDate914, 24200 × 30Dropdown · Single select
3Button1126, 26136 × 26ClearAllSlicers
4Card (رقم)[A Window label]344, 40300 × 24Segoe UI 10 · #6B634B
5Card (رقم)[A On site]104, 112127 × 38DIN 22 · #343631
6Card (رقم)[A Attendance %]301, 112127 × 38DIN 22 · #343631
7Card (رقم)[A Absent]498, 112127 × 38DIN 22 · #343631
8Card (رقم)[A Coverage %]695, 112127 × 38DIN 22 · #343631
9Card (رقم)[A Avg on site per day]892, 112127 × 38DIN 22 · #343631
10Card (رقم)[A Active headcount]1089, 112127 × 38DIN 22 · #343631
11Card (رقم)[A Sub on site]104, 150165 × 24Segoe UI 7.5 · #6B6E66
12Card (رقم)[A Sub absent]498, 150165 × 24Segoe UI 7.5 · #6B6E66
13Card (رقم)[A Sub coverage]695, 150165 × 24Segoe UI 7.5 · #6B6E66
14Card (رقم)[A Sub people]892, 150165 × 24Segoe UI 7.5 · #6B6E66
15Stacked columnDate [A On site in window] [A On site rest of month]108, 240672 × 172لون #B8A567 · Labels on · Legend off
16DonutPresence [A Records]822, 240426 × 172لون #154423 · Labels on · Legend Right
17MatrixArea Shift [A On site]108, 486402 × 206ستايل الجدول الموحد · Image 22×auto
18TableDate EmployeeName Area Craft Shift Presence552, 486696 × 206ستايل الجدول الموحد · Image 22×auto

أوامر العمل · Work orders

نسبة الوقائي، الطوارئ، الالتزام بالجدول، عمر المفتوح، وأكثر المعدات أعطالًا.

خلفية صفحة أوامر العمل
#النوعالحقولX, YW × Hالتنسيق
1SlicerCrew662, 22250 × 34Tile أفقي · Multi select
2SlicerTrain922, 22340 × 34Tile أفقي · Multi select
3Card (رقم)[W Total]104, 112127 × 38DIN 22 · #343631
4Card (رقم)[W PM %]301, 112127 × 38DIN 22 · #343631
5Card (رقم)[W Emergency %]498, 112127 × 38DIN 22 · #343631
6Card (رقم)[W Schedule compliance %]695, 112127 × 38DIN 22 · #343631
7Card (رقم)[W MH variance %]892, 112127 × 38DIN 22 · #343631
8Card (رقم)[W Open]1089, 112127 × 38DIN 22 · #343631
9Card (رقم)[W Sub total]104, 150165 × 24Segoe UI 7.5 · #6B6E66
10Card (رقم)[W Sub PM]301, 150165 × 24Segoe UI 7.5 · #6B6E66
11Card (رقم)[W Sub EM]498, 150165 × 24Segoe UI 7.5 · #6B6E66
12Card (رقم)[W Sub SC]695, 150165 × 24Segoe UI 7.5 · #6B6E66
13Card (رقم)[W Sub MH]892, 150165 × 24Segoe UI 7.5 · #6B6E66
14Line & stacked columnMonth [W PM] [W CM] [W PM %] [W PM target]108, 240732 × 180لون #B8A567 · Labels off · Legend Top
15Clustered columnOpen age [W Open]882, 240366 × 180لون #007A3D · Labels on · Legend off
16Clustered barAssetKey [W Emergencies]108, 494532 × 198لون #8A340F · Labels on · Legend off
17MatrixTrain Month [W Total]682, 494566 × 198ستايل الجدول الموحد · Image 22×auto

قطع الغيار · Spare parts

صحة المخزون، القطع الحرجة، واللي في الإصلاح أو الطلب.

خلفية صفحة قطع الغيار
#النوعالحقولX, YW × Hالتنسيق
1SlicerCategory742, 24190 × 30Dropdown · Multi select
2SlicerCriticality944, 22160 × 34Tile أفقي · Multi select
3Button1112, 26150 × 26ClearAllSlicers
4Card (رقم)[S Items]104, 112127 × 38DIN 22 · #343631
5Card (رقم)[S Healthy %]301, 112127 × 38DIN 22 · #343631
6Card (رقم)[S Out of stock]498, 112127 × 38DIN 22 · #8A340F
7Card (رقم)[S Critical at risk]695, 112127 × 38DIN 22 · #8A340F
8Card (رقم)[S Under repair]892, 112127 × 38DIN 22 · #343631
9Card (رقم)[S Stock value]1089, 112127 × 38DIN 22 · #343631
10Card (رقم)[S Sub critical]695, 150165 × 24Segoe UI 7.5 · #6B6E66
11Card (رقم)[S Sub repair]892, 150165 × 24Segoe UI 7.5 · #6B6E66
12Card (رقم)[S Sub value]1089, 150165 × 24Segoe UI 7.5 · #6B6E66
13DonutStock health [S Items]108, 240352 × 176لون #8A340F · Labels on · Legend Right
14Stacked barCategory Stock health [S Items]502, 240352 × 176لون #8A340F · Labels off · Legend off
15TableDescription Status Expected date Days to expected896, 240352 × 176ستايل الجدول الموحد · Image 22×auto
16TablePart No Description Area Criticality Location [S Stock bar] Min Reorder point Stock health Status Repair / order ref108, 4901140 × 202ستايل الجدول الموحد · Image 24×204
  1. ابني صفحة الصفحة الرئيسية
    خلفيتها ← visuals من فوق لتحت ← Format painter ← قارني بالصورة.
  2. ابني صفحة الاجتماع الصباحي
    خلفيتها ← visuals من فوق لتحت ← Format painter ← قارني بالصورة.
  3. ابني صفحة حماية HEMAYA
    خلفيتها ← visuals من فوق لتحت ← Format painter ← قارني بالصورة.
  4. ابني صفحة الحضور
    خلفيتها ← visuals من فوق لتحت ← Format painter ← قارني بالصورة.
  5. ابني صفحة أوامر العمل
    خلفيتها ← visuals من فوق لتحت ← Format painter ← قارني بالصورة.
  6. ابني صفحة قطع الغيار
    خلفيتها ← visuals من فوق لتحت ← Format painter ← قارني بالصورة.
  7. اختبري التنقل والفلاتر في كل صفحة
    كل زر يودي لصفحته، وزر Clear all slicers في الحضور وقطع الغيار يرجع الفلاتر.

المرحلة 6

التحديث والنشر

أرقام تتأكدين منها (البيانات التجريبية)

المؤشرالمفروض
ملاحظات HEMAYA140
المتأخرة14
نسبة الإغلاق82.9%
قطع الغيار28
نافدة من المخزون9
قطع حرجة (A) في خطر6

إذا طلعت نفس الأرقام، بناؤك مطابق للأصل. بعدها امسحي الصفوف المكتوب عليها DUMMY sample من Excel، وحطي البيانات الحقيقية بنفس الأعمدة.

  1. Refresh وقارني الأرقام الست
  2. استبدلي البيانات التجريبية بالحقيقية
    في Daily_Inputs.xlsx: HEMAYA_Log و Spares_Register.
  3. Publish إلى Workspace القسم
    Home ← Publish.
  4. أدخلي بيانات الدخول وجدولي التحديث
    Semantic model ← Settings ← Data source credentials ← OAuth2. وScheduled refresh يوميًا 09:00 و 13:00.
  5. شاركي كـ App مع الإدارة

قبل ما تعتمدينه

ملاحظات صريحة على الملف الحالي

هذي أشياء لقيتها وأنا أقرأ الملف. ما تمنع البناء، بس الأفضل تعرفينها:

الملاحظةوش أسوي
صفحة الحضور تقرأ ملف الحضور القديم PAP_Attendance.xlsx، ورقم الموظف فيه SIS مو رقم معادن.لما تبنين ملف الحضور الجديد (دليل بناء حضور PAP)، غيري مصدر Attendance و Employees وأسماء الأعمدة: MaadenID بدل EmployeeID.
بيانات HEMAYA وقطع الغيار تجريبية.المرحلة 6: امسحي DUMMY وحطي الحقيقي.
جدول Calendar يغطي 2026 بس (365 يوم من 1 يناير).غيري في كوده List.Dates(D0, 365, …) إلى عدد أيام أكبر، أو خلي النهاية تاريخ اليوم.
أهداف مكتوبة داخل المقاييس: الوقائي 80%، الالتزام 85%، الطوارئ 5%.تأكدي منها مع مديرك. والأفضل تنقل لجدول أهداف (فيه Targets.csv جاهز في 01_WorkOrders).
في HEMAYA، Days open و Overdue تنحسب لين آخر تاريخ رصد مو اليوم. هذا مناسب للبيانات التجريبية.مع البيانات الحقيقية غيري Ref = List.Max(Typed[Reported]) إلى Ref = Date.From(DateTime.LocalNow()).
3 رسوم دونات (HEMAYA، الحضور، قطع الغيار).اختياري: Clustered bar أوضح للمقارنة، حسب إرشادات مايكروسوفت.
شيت Spare_Parts وعمود Start في Activities موجودين في Excel وما ينقرون.لا شي، إلا إذا تبين تعرضينهم.

انولد هذا الدليل مباشرة من PAP_Maintenance_Hub.pbip بتاريخ 14 سبتمبر 2026. أي تعديل على الملف بعد هذا التاريخ ما يظهر هنا.