פתרון ללא קוד: הצגת הימים מאז שינוי אחרון של פריט רשימה

מאת ג'סטין ג'ויס, LANtek

הערה

מאמר זה מהווה חלק מאוסף של רשומות מארבע שנות הבלוג Get the Point עבור משתמשי קצה של SharePoint.

מבט כולל: דוחות התיישנות מותאמים אישית ללא קוד

אחד מהחלקים הפונקציונליים של אתר SharePoint שלעתים תכופות מתבקשים הוא דוח התיישנות עבור משימות או פריטי רשימה. במילים אחרות, כמה ימים/חודשים עברו מאז שפריט רשימה זה שונה לאחרונה?

על פני השטח זו נראית כבקשה פשוטה מאוד. אחרי הכל, יש לנו תאריכים לפריטים שנוצרים ומשנים, יש לנו את היכולת לאחסן תאריכים מותאמים אישית כאשר שינויים מסוימים בפריטים מתרחשים באמצעות מקלטי אירועים. חישבנו עמודות שבהן אנו יכולים לכלול נוסחאות דמויות Excel כדי לעבוד עם המידע שלנו. זו נראית כמו הצעה די ישירה. אנו בוחרים שדה תאריך, יוצרים עמודה מחושבת ולאחר מכן מבצעים נוסחה בסגנון [DateField] - [Today]. אה, אבל לא כל כך מהר! כפי שיודע כל מי שניסה את המשימה ה"פשוטה" הזו, ניסיון להשתמש במשהו כמו [Today] בעמודה מחושבת גורם לבעיות. ניסיון להוסיף את [Today] לתיבת הנוסחה של העמודה המחושבת יספק לך הודעת שגיאה דומה לזו:

הודעת שגיאה

מדוע? ובכן, זה קשור לאופן שבו עמודות מחושבות מחושבות.

ניקח נוסחה פשוטה כדוגמה:

= IF( [Column1]<=[Column2], "OK", "Not OK")

כל מה שכתוב הוא שאם Column1 קטן מ- Column2 או שווה לו, הצג OK, אחרת הצג Not OK. זוהי נוסחה בסיסית אופיינית למדי עבור עמודה מחושבת, והיא מניחה הנחה בסיסית לגבי פריט הרשימה המכיל עמודות אלה: הערכים עבור Column1 ו- Column2 לעולם לא יוכלו להשתנות ללא אירוע עדכון בפריט הרשימה.

זה נכון, עמודות מחושבות יחושבו מחדש רק כאשר הרשימה מתעדכנת (או נוצרת) מאחר שהן מניחות שהמידע שאתה מחשב כלול בפריט עצמו. הדבר יוצר בעיה כאשר אתה מנסה להשתמש בפריט שמשתנה ללא תלות בשדות של הפריט, כגון התאריך של היום.

עכשיו לא הייתי בפגישה שבה הם החליטו שזו הדרך שבה עמודות מחושבות יתפקדו, עם זאת, אם הייתי צריך לנחש בצורה מושכלת הייתי מניח שהן מתפקדות כך מבחינת ביצועים. תארו לעצמכם שהייתה לכם רשימה של כמה אלפי פריטים, שכל אחד מהם הכיל עמודה מחושבת שהייתה זקוקה לעדכון "חי". זה אומר שמנגנון כלשהו, אולי עבודת טיימר, יצטרך לחזור על כל פריט שהכיל את העמודה המחושבת מדי פעם ולעדכן את ערכו. זה יכול להיות מכביד מאוד מבחינת ביצועים מכיוון שעם פריסות גדולות יותר העבודה הזו עשויה לרוץ ולשנות דברים כל הזמן. זה רק הניחוש שלי, אבל זה די הגיוני אם חושבים על זה.

קיימות כמה הצעות לפתרונות דומים שכוללים הונאה של SharePoint לקבלת ערך 'היום' על-ידי יצירת עמודה בשם Today תחילה, הוספתה לנוסחה ולאחר מכן מחיקתה. כל אלה טובים ויפים, אבל זכור מה אמרתי על עדכון עמודות מחושבות. ערך זה ישתנה רק כאשר הפריט יתעדכן, כלומר הערכים יהיו שגויים בקרוב, במיוחד במקרה של חישוב יום.

ראיתי אחרים משתמשים ב-JavaScript חכם כדי לכתוב את הערכים לדף. גם זה יעבוד, אבל אני די מתנגד באופן מוחלט לתסריט לקוח כשאפשר להימנע ממנו.

יישום:

אז מה לעשות? עמודות מחושבות אינן באות בחשבון עבור מה שנקרא פונקציות "נדידות", כמו Today. ייתכן שנוכל לפתח קוד מותאם אישית שיטפל בזה עבורנו כמו עמודה מחושבת, עבודת טיימר או תהליך מתוזמן שיבוא ויעדכן כל פריט בודד שצריך לבצע את החישוב הזה. זה מחזיר אותנו לבעיית הביצועים שהזכרתי בפסקה האחרונה, ובנוסף זה פתרון שביר שיהיה מאוד ספציפי לאתר/רשימה/עמודה המדוברת. בנוסף לשני החששות הללו, תצטרך גם ללכת למצוא בחור חנון, כמוני, שיודע לתכנת ולשכנע אותו לפתח את הפתרון הזה עבורך. אבל יש דרך קלה יותר!

אם יש לך זכויות ליצור שדות ולערוך דפים באתר שלך, ויש לך מעט ידע על XSLT ויצירת תצוגות, אתה יכול להרכיב תבנית XSL שניתן לכלול בתצוגת רשימה ותחשב את הערך שלך בנאמנות בכל פעם שהדף מתבקש. תרחיש זה מסיר את הדאגה שלנו לגבי הביצועים, ואינו דורש פיתוח ופריסה של קוד מותאם אישית באמצעות פתרון.

מושלם. אז איך עושים את זה?

  1. צור או בחר את השדה שישמש כמקור שלנו. עליו להיות סוג תאריך.
  2. צור את השדה שלנו שישמש כמציין מיקום עבור הערך המחושב.
  3. הוסף את שני השדות הללו לסוג תוכן והוסף סוג תוכן זה לרשימה.
  4. צור תצוגה של רשימה זו המכילה הן את עמודת המקור והן את עמודות מציין המיקום.
  5. העלה את תבנית XSL לספריית הסגנונות.
  6. הגדר את המאפיין 'קישור XSL' עבור ה- Web Part של תצוגת רשימה דרך ממשק המשתמש.
  7. הצלחה!

בוא נבחן מקרה שימוש לדוגמה ונעבור על ההטמעה. הלקוח שלנו רצה תצוגה של הרשימה הראשית שלו, שתגלה לו כמה זמן פריט רשימה מסוים ישב במצבו. רשימה זו הכילה סוג תוכן אתר מותאם אישית שנגזר מסוג הפריט ונוסף לרשימה. כבר היה במקום מקלט אירועים שלוכד כל פעם ששדה המצב בפריט הרשימה השתנה ושמר תאריך זה בעמודה בשם "תאריך סטטוס השתנה". כל החיווט הזה אינו נדרש, וניתן לעשות אותו עם כל שדה תאריך (במקרה זה היישום שלנו אבל אל תהסס להתנסות). המינימום הדרוש לך הוא שדה תאריך המקור ושדה מציין המיקום כדי להחזיק את החישוב שלך (עוד על כך בפסקה הבאה) שיוספו לרשימה שלך, אם כי אני מציע לך להשתמש בעמודות אתר ובסוגי תוכן אתר למקרה שתרצה לעשות שימוש חוזר בפתרון זה במקומות אחרים באתר שלך.

אז יש לנו את תאריך המקור שלנו שנוכל להשתמש בו בחישוב שלנו מול התאריך של היום. כעת ניתן ליצור עמודת אתר מותאמת אישית שתשמש כגורם מכיל עבור הערך המחושב שלנו. במקרה זה בחרתי להשתמש בעמודה מחושבת מכיוון שלא ניתן יהיה לשנות אותה בטפסים החדשים או לערוך פריטים, אך ניתן לבחור אותה להצגה בתצוגות מכיוון שאיננו רוצים שמשתמשים יזינו ערכים שרירותיים בעמודה זו. זה יכול להיות מבלבל למה זה לא מוצג בתצוגות וכו'.

כעת, כשיש לנו את עמודת האתר שלנו, נוכל להוסיף אותה לסוגי התוכן שלנו שישמשו ברשימה שלנו. לאחר מכן, עלינו ליצור את התצוגה שלנו שמאוחר יותר תותאם אישית עם ה- XSLT שלנו. הקפד ליצור תצוגה רגילה המכילה את עמודת תאריך המקור ואת העמודה המחושבת החדשה שתפעל כמציין מיקום עבור הערך המחושב.

כעת יש לנו את כל מה שנצטרך כדי לתמוך בדוח ההזדקנות המותאם אישית שלנו. כל שנותר הוא ליצור את תבנית ה-XSL שלנו, להעלות אותה לספריית הסגנונות של האתר ולקשר אותה לתצוגת הרשימה שלנו. תבנית XSL שבה נשתמש תכיל סימון רגיל שנוצר על ידי SharePoint ליצירת התצוגה, כמו גם סימון מותאם אישית משלנו המשמש לעקיפת חלקים מסוימים של זה ולחשב את הערך הרצוי עבורנו.

כדי לתת קרדיט היכן שמגיע קרדיט, תבניות ה-XSL לביצוע החישובים בפועל שאני משתמש בהן עבור פתרון זה סופקו באדיבות על ידי "swirch" בפורומים של MSDN:
http://social.msdn.microsoft.com/Forums/en-US/sharepointcustomization/thread/aeda905b-9bc6-40c4-bd22-21306c5cb0d2/

הורד את גליון הסגנונות של XSL (aging.zip) שהרכבתי כאן:
https://OneDrive.live.com/?cid=c262e8e2d59a86d9&permissionsChanged=1&id=C262E8E2D59A86D9!104

בפתיחת זה בעורך הטקסט המועדף עליך תראה הרבה סימוני SharePoint XSL רגילים לעיבוד התצוגות, אם תמשיך לגלול מטה לשורה 357 תראה את ההתחלה של התבניות המותאמות אישית שהוספתי לסימון, הראשונה היא התבנית "DateDiff" ואחריה "חישוב-יוליאן-יום" ו-"FieldRef_printTableCell_EcbAllowed.Days_x0020_At_x0020_Status". אלה שלוש התבניות שלנו שיבצעו ויציגו את החישובים שלנו בתצוגות שלנו. אם בכוונתך להשתמש בשמות שדות שונים מאלה שצוינו קודם לכן במאמר זה, תצטרך לעבור על התבניות הללו ולהחליף את כל ההפניות לשמות האחרים. זכור, לשם כך תרצה להשתמש בשם הפנימי של השדה ולא בשם התצוגה.

לאחר שתהיו בטוחים שהתבנית מוכנה, נווטו אל ספריית הסגנונות שלכם והעלו אותה תחת התיקייה "XSL Style Sheets" ולאחר מכן העתק את הקישור לקובץ. זה יאפשר לנו לבצע בו שינויים בקלות מאוחר יותר, או להוסיף אותו לחלקים שונים באתר כרצוננו.

לאחר מכן, עבור אל הרשימה שלך ובחר את התצוגה שיצרת קודם לכן במאמר זה. מתפריט "פעולות אתר" לחץ על "ערוך דף".

הפקודה 'ערוך דף' בתפריט 'פעולות אתר'

אתר את ה- Web Part של תצוגת רשימה בדף ופתח את תפריט ה- Web Part על-ידי לחיצה על החץ הקטן הפונה כלפי מטה בפינה השמאלית העליונה. מתפריט זה, בחר 'ערוך Web Part'.

עריכת פקודה של Web Part בתפריט Web Part

פעולה זו תפתח את תפריט ה- Web Part בצד השמאלי של חלון הדפדפן.

תפריט Web Part

לחץ על + עבור הסעיף "שונות" ואתר את המאפיין "קישור XSL".

המאפיין 'קישור XSL' בתפריט Web Part

הדבק את הקישור לקובץ ה- XSL בספריית הסגנונות שהעתקת קודם לכן (קישור זה יכול להיות קישור יחסי או מוחלט).

קישור קובץ XSL מודבק

לחץ על 'אישור' כדי לשמור את השינויים ולאחר מכן לחץ על לחצן 'הפסק עריכה' ברצועת הכלים 'דף' בחלק העליון של הדף.

לחצן 'הפסק עריכה' בכרטיסיה 'דף'

אם הכל הוגדר כראוי, כעת אתה אמור לראות מספרים בעמודה "ימים במצב".

העמודה 'ימים במצב' מציגה מספר

ולבסוף, כך זה ייראה עם כמה נתוני בדיקה של תאריכים שונים:

דוח התיישנות מציג נתוני בדיקה

‏‏תקציר:

הנה זה: דרך מעוצבת יפה, חזקה ובעלת ביצועים טובים יותר ליצירת דוח התיישנות ב- SharePoint, עם יישום פשוט ללא קוד. יש לכך לא מעט יישומים פוטנציאליים מלבד מקרה השימוש היחיד שחקרנו כאן. תרחיש נפוץ נוסף עבור דוח מסוג זה הוא צירופו לרשימת משימות כדי שתוכל לראות במבט מהיר כמה זמן עבר מאז שמשימה נוצרה.

בהצלחה!

--ג'סטין

ג'סטין ג'ויס, LANtek

הערות

שלבים חסרים
08/10/2012 03:51
אוקיי עקבתי אחר השלבים, אבל כנראה שחסר משהו - איך ה-XSL יידע באיזה תאריך להשתמש, או באיזה שדה להוסיף את הימים מאז? שונא את זה כשמפספסים שלבים.

ללא קוד, מסכים!
30/08/2012 12:12 PM
אני מסכים - אני לא חושב שזה באמת נחשב ל"אין קוד".
מעניין שבגלל איזושהי של SharePoint, יש לי עמודה מחושבת שעובדת באמצעות Today... לא בטוח איך ולמה כי אני לא מצליח לגרום לו לעשות את זה שוב, אבל זה עדיין שם ועובד.

הנוסחה עבור העמודה המחושבת "ימים במצב"?
02/05/2012 07:39 AM
חגי - מהי הנוסחה שבה השתמשת עבור עמודת האתר המחושבת "ימים במצב" (עמודת מציין מיקום)? האם זה היה "=היום"?

SharePoint 2007
02/12/2011 11:29 AM
נכון לעכשיו לא ניסיתי ליישם פתרון זה על SharePoint 2007, אולם אני בודק אותו. למרבה הצער, אין מאפיין XslLink שמופיע ב- Web Part דרך ממשק המשתמש.

פוסט נהדר
30/11/2011 09:53 AM
שלום,
פוסט נהדר.
אני משתמש ב- SharePoint 2007.
אין לי קטע שונות כפי שצוין לעיל.
האם יש לך שלבים עבור תצורת SP2007?
תודה.

Re: פתרון ללא קוד: הצגת הימים מאז שינוי אחרון של פריט רשימה ב- SharePoint
11/10/2011 08:24 AM
היי כריס.
ממצא נהדר!
אני הולך להסתכל על מה שפרסמת בתקווה מאוחר יותר היום ולראות אם אני יכול להפוך את הפתרון הזה לקצת יותר חזק.
אני שמח שאהבת את הפוסט, ואני שמח מאוד שהצלחת למצוא פתרון לפורמט התאריך האירופי. :)
-ג'סטין

פתרון עבור תבניות תאריך אירופאיות
10/11/2011 6:45 AM
שוב שלום ג'סטין,
לידיעתך, מצאתי פתרון לבעיה שהזכרתי קודם בדף זה;
https://sharepointbydummies.wordpress.com/2011/07/13/possible-work-around-to-date-format-issue-sharepoint-2010/

תבניות תאריך אירופאיות
07/10/2011 03:59
היי ג'סטין,
זה פתרון ממש טוב תודה, ובדיוק מסוג הדברים שביליתי ביומיים האחרונים בחיפוש! עם זאת יש לי קצת בעיה עם זה וקיוויתי שתוכל לעזור לי.
שיניתי מעט את הקוד שלך כדי לחשב את מספר הימים עד שמשהו יקרה, ולא מאז, על ידי החלפת המשתנים בשורה האחרונה של פונקציית "DateDiff";

<xsl:value-of select="$JulianToday - $JulianStartDate"></xsl:value-of>

עם זאת, אני מצליח לגרום לו לקלקל את ההבדל בצורה נכונה רק בחצי מהזמן. כך למשל עם התאריך הזה (פורמט dd/MM/yyyy);

30/12/2011

החישוב בוצע כהלכה, אך עם תאריך זה (אותה תבנית)

12/10/2011

הוא מחשב כאילו 10 בדצמבר 2011 ולא 12 באוקטובר 2011.
ניסיתי פשוט להחליף את המיקומים של ערכי היום והחודש במשתנה "JulianStartDate", כך;

<xsl:with-param name="Month" select="substring(ddwrt:FormatDateTime(string($StartDate), 1033, 'yyyyMMdd'),7,2)"/>
<xsl:with-param name="Day" select="substring(ddwrt:FormatDateTime(string($StartDate), 1033, 'yyyyMMdd'),5,2)"/>

וזה תיקן את הבעיה עם הדייט השני, אולם אז זה היה שגוי לדייט הראשון!
ניסיתי גם לשנות את קריאות FormatDateTime כך שישתמשו ב-LCIDs אירופיים ושינויים שונים בפרמטר האחרון של FormatDateTime (למשל ddMMyyyy, MMddyyyy) עם ההתאמות המתאימות לפרמטרים המיקומיים של תת-המחרוזת ללא הצלחה.
אודה מאוד לכל עצה שתוכל להציע.
תודה!
אנונימי

No-Code
21/09/2011 04:27 AM
אני לא חושב ש-XSL מתאים כפתרון "ללא קוד", מכיוון שהבנת שפת ה-XSL אינה מתאימה לכולם - אולם היא אינה כרוכה בתכנות. חוץ מזה: פתרון נחמד, תודה!