דילוג לתוכן

תכנות

4.8k נושאים 39.3k פוסטים

קטגוריות משנה


  • 22 נושאים
    137 פוסטים
    katzK

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

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

    נתחיל...

    שלב א:

    ראשית בקובץ ה- Excel של רשימת הנמענים, הוסיפו לטבלת הנתונים ארבעה עמודות בשמות כדלהלן (חשוב שהשמות יהיו מדויקים ללא רווחים מיותרים - לתשומת ליבכם):

    DocFolderPath

    DocFileName

    PdfFolderPath

    PdfFileName

    שלב ב:
    צרו שתי תיקיות נפרדות, אחד לקבצי הפלט בפורמט docx, ואחד לקבצי הקלט בפורמט pdf, העתיקו את נתיב התיקייה של קבצי ה- docx והדביקו אותם עבור כל רשומה בשדה שיצרתם בשם DocFolderPath, לאחמ"כ חזרו על הפעולה והפעם העתיקו את נתיב התיקייה של קובצי ה- PDF והדביקו בשדה PdfFolderPath.
    בשדה DocFileName כתבו את השם של הקובץ עבור הרשומה - ניתן להשתמש בנוסחאות, כמו"כ בשדה PdfFileName כתבו את שם הקובץ כנ"ל.

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

    שלב ד:
    פתחו את לשונית מפתחים בקובץ ה- word פתחו את עורך הקוד הוסיפו מודל חדש מצו"ב צילום מסך:
    3eb2538f-9ab1-41eb-a1df-452212916da6-image.png

    הדביקו את הקוד הבא:

    Sub MailMergeToPdfBasic() ' Mark the start of the Subroutine (i.e. Macro) and name it "MailMergeToPdf" ' Macro created by Imnoss Ltd ' Please share freely while retaining attribution ' Last Updated 2021-05-03 Dim masterDoc As Document, singleDoc As Document, lastRecordNum As Long ' Create variables ("Post-it Notes") for later use Set masterDoc = ActiveDocument ' Identify the ActiveDocument (foremost doc when Macro run) as "masterDoc" masterDoc.MailMerge.DataSource.ActiveRecord = wdLastRecord ' jump to the last active record (active = ticked in edit recipients) lastRecordNum = masterDoc.MailMerge.DataSource.ActiveRecord ' retrieve the record number of the last active record so we know when to stop masterDoc.MailMerge.DataSource.ActiveRecord = wdFirstRecord ' jump to the first active record (active = ticked in edit recipients) Do While lastRecordNum > 0 ' create a loop, lastRecordNum is used to end the loop by setting to zero (see below) masterDoc.MailMerge.Destination = wdSendToNewDocument ' Identify that we are creating a word docx (and no e.g. an email) masterDoc.MailMerge.DataSource.FirstRecord = masterDoc.MailMerge.DataSource.ActiveRecord ' Limit the selection to just one document by setting the start ... masterDoc.MailMerge.DataSource.LastRecord = masterDoc.MailMerge.DataSource.ActiveRecord ' ... and end points to the active record masterDoc.MailMerge.Execute False ' run the MailMerge based on the above settings (i.e. for one record) Set singleDoc = ActiveDocument ' Identify the ActiveDocument (foremost doc after running the MailMerge) as "singleDoc" singleDoc.SaveAs2 _ FileName:=masterDoc.MailMerge.DataSource.DataFields("DocFolderPath").Value & Application.PathSeparator & _ masterDoc.MailMerge.DataSource.DataFields("DocFileName").Value & ".docx", _ FileFormat:=wdFormatXMLDocument ' Save "singleDoc" as a word docx with the details provided in the DocFolderPath and DocFileName fields in the MailMerge data singleDoc.ExportAsFixedFormat _ OutputFileName:=masterDoc.MailMerge.DataSource.DataFields("PdfFolderPath").Value & Application.PathSeparator & _ masterDoc.MailMerge.DataSource.DataFields("PdfFileName").Value & ".pdf", _ ExportFormat:=wdExportFormatPDF ' Export "singleDoc" as a PDF with the details provided in the PdfFolderPath and PdfFileName fields in the MailMerge data singleDoc.Close False ' Close "singleDoc", the variable "singleDoc" can now be used for the next record when created If masterDoc.MailMerge.DataSource.ActiveRecord >= lastRecordNum Then ' test if we have just created a document for the last record lastRecordNum = 0 ' if so we set lastRecordNum to zero to indicate that the loop should end Else masterDoc.MailMerge.DataSource.ActiveRecord = wdNextRecord ' otherwise go to the next active record End If Loop ' loop back to the Do start End Sub ' Mark the end of the Subroutine

    שלב ה וסיום:
    סגרו את עורך הקוד.
    לחצו על כפתור פקודות מאקרו שבכרטיסיית מפתחים, בחרו את המאקרו בשם MailMergeToPdfBasic ולחצו הפעל מצו"ב צילום מסך
    3890ce69-c0e9-4f30-89ce-3e97b7de750b-image.png

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

    מקור

  • ארכיון האתר הקודם והחביב קוד-613

    1k נושאים
    10k פוסטים
    chagoldC

    @אבי אמר בשוב, צילומי הצ'קים בבנקים:

    התעסקתי לאחרונה עם סורקים של חברת MAGTEK, הם ידידותיים ונוחים להתממשקות, אבל כמדומני שהבנקים בישראל מוכנים לקבל סריקות רק מסורקים של חברת PANINI

    @אבי איך יוצרים אתך קשר?

  • 31 נושאים
    133 פוסטים
    Y.Excel.AccessY

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

    CHOOSECOLS לבחירת עמודות ממערך CHOOSEROWS לבחירת שורות ממערך WRAPROWS להמרת מערך חד ממדי לרב ממדי - פריסה לשורות WRAPCOLS כנ"ל - פריסה לעמודות HSTACK ו VSTACK - הפעולה של {} אך בלי סוגריים - לא משמעותי לכאורה

    והעולה על כולנה, סוף סוף:

    LET - ליצירת משתנים.

    כל אלו מצטרפות לפונקציות שנוספו מוקדם יותר -
    https://blog.sheetgo.com/google-sheets-formulas/10-new-google-sheets-functions/

    וכלול בתוכם - LAMBDA, MAP (חלקי - לא עובד לקנן ב MAP ודומיו מערכים אחרים), פונקציות בעלות שם, וכו' ע"ש בקישור.

  • קוד להצגת התקדמות ב-statusbar של וורד

    1
    5 הצבעות
    1 פוסטים
    184 צפיות
    אין תגובות
  • באג ב-vba בפונקציה Selection.Information(wdVerticalPositionRelativeToPage)

    5
    0 הצבעות
    5 פוסטים
    360 צפיות
    pcinfogmachP

    @yossiz
    ייתכן שאתה צודק ואין פתרון.
    ולו יהא זה שכרי בפתיחת הפוסט שכל מורט בשער ראשו יידע מה מקור עצביו.

    אגב ההשוואה בין הטורים רק הבאתי את זה כדוגמא
    זה רלונטי לכל מיקום מדוייק של שני אובייקטים במסמך

  • בקשת cURL לnginx שעובדת מהקונסול אבל לא מתוך PHP

    20
    0 הצבעות
    20 פוסטים
    725 צפיות
    Aharon 0A

    תתחיל מזה שתשנה את הפורט מ 200 למעל 1024, וחוץ מזה תבדוק שאתה לא נופל על פורט שמור:
    https://www.geeksforgeeks.org/50-common-ports-you-should-know/

  • עזרה בשימוש בrclone

    14
    0 הצבעות
    14 פוסטים
    676 צפיות
    A0533057932A

    @צדיק-תמים כתב בעזרה בשימוש בrclone:

    @A0533057932 כתב בעזרה בשימוש בrclone:

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

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

    עדכון
    עברו 21 ימים
    ואכן זה עובד בהצלחה

  • איך לזהות פונטים עבריים ב-C#

    3
    0 הצבעות
    3 פוסטים
    357 צפיות
    yossizY

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

    At this time, there is no mechanism to enumerate fonts supporting arbitrary scripts or character ranges in Unicode. The NEWTEXTMETRICEX structure passed by EnumFontFamExProc includes the FONTSIGNATURE structure, which includes more detailed declarations provided by the font developer as to what code pages and what Unicode ranges the font supports. To determine more precisely what character ranges a given font supports, select the font into a device context and call GetFontUnicodeRanges

  • איך אני מתכנת קורא כרטיסם EMV

    3
    -1 הצבעות
    3 פוסטים
    397 צפיות
    chagoldC

    https://he.aliexpress.com/item/1005008263708810.html?spm=a2g0o.detail.pcDetailTopMoreOtherSeller.12.2e8eu7SSu7SSER&gps-id=pcDetailTopMoreOtherSeller&scm=1007.40196.366991.0&scm_id=1007.40196.366991.0&scm-url=1007.40196.366991.0&pvid=68056091-3918-4744-8504-f2ca3e8df7d4&_t=gps-id:pcDetailTopMoreOtherSeller,scm-url:1007.40196.366991.0,pvid:68056091-3918-4744-8504-f2ca3e8df7d4,tpp_buckets:668%232846%238107%231934&pdp_npi=4%40dis!ILS!22.38!18.33!!!43.66!35.76!%402141001d17354107094283732e9649!12000044408826047!rec!IL!!ABX&utparam-url=scene%3ApcDetailTopMoreOtherSeller|query_from%3A#nav-specification:~:text=בבקשה לבקש את התוכנה מספק כרטיס החכם

  • 0 הצבעות
    36 פוסטים
    2k צפיות
    O

    @Aharon-0 כתב באיך שולטים על מזגן תדיראן באמצעות Home Assistant‬ (או דבר אחר יותר טוב)?:

    @one1010 כתב באיך שולטים על מזגן תדיראן באמצעות Home Assistant‬ (או דבר אחר יותר טוב)?:

    @Aharon-0 כתב באיך שולטים על מזגן תדיראן באמצעות Home Assistant‬ (או דבר אחר יותר טוב)?:

    @ששא נתקלתי בתוסף הזה, לפי ה-GIT זה נראה מעודכן אשמח לבדיקתך:
    https://www.home-assistant.io/integrations/gree/

    נראה שזה תומך רק במקרה שיש התקן WIFI של היצרן ועובד רק עם האפליקציה של המזגן.

    לפי מה שקראתי בתיעוד זה משתמש בכתובות ip ו mac של המזגן, השימוש באפליקציה זה רק לרישום ברשת

    29f68b06-6a91-4d0b-9d5a-f34983c2b04a-image.png

  • תגובות ל"צלילה לעומק TypeScript"

    1
    1 הצבעות
    1 פוסטים
    274 צפיות
    אין תגובות
  • מסד נתונים קיים ולא קיים בmysql

    6
    0 הצבעות
    6 פוסטים
    457 צפיות
    ש

    @dovid אני מקווה שהחברה פה לא יתעצבנו, אבל שאלתי את GPT מה הוא אומר, אז הוא כתב לי שאני אבדוק פה

    SELECT SCHEMA_NAME FROM information_schema.SCHEMATA WHERE SCHEMA_NAME LIKE '%old%';

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

  • 0 הצבעות
    1 פוסטים
    260 צפיות
    אין תגובות
  • סקיצה איך ליישם Theming ב- wpf בצורה קלה ונוחה

    6
    2 הצבעות
    6 פוסטים
    405 צפיות
    קומפיונטק

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

    אם אתה רוצה לראות סתם גלריית theme שבנויה עם avalonia, תוריד את זה: (צריך להיות מחובר לחשבון GitHub)
    https://github.com/kikipoulet/SukiUI/actions/runs/12388950546/artifacts/2336318341

  • Wpf: איך ליישם dataconext עבור style בתוך resource dictionary ??

    5
    0 הצבעות
    5 פוסטים
    378 צפיות
    pcinfogmachP

    @dovid
    נגיד אני רוצה מבנה נתונים של תיקייות ומסמכים ב-treeview ואני בונה לזה מודל ו style יפה שאמור לשמש אותי בכמה תוכנות
    לצרף גם קוד דוגמא?

  • GitHub Copilot עכשיו בחינם

    3
    8 הצבעות
    3 פוסטים
    475 צפיות
    yossizY

    @קומפיונט כתב בGitHub Copilot עכשיו בחינם:

    ואגב, למי שלא אוהב לשתף קטעי קוד שלו עם GitHub

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

  • עדכון ושדרוג פורום NodeBB

    2
    0 הצבעות
    2 פוסטים
    399 צפיות
    yossizY

    @קן-ציפור כתב בעדכון ושדרוג פורום NodeBB:

    האם שווה לקחת את הסיכון לשדרג?

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

    💡 אפשר לבדוק איזה שידרוגי DB יש בגירסה מסויימת על ידי

    ls src/upgrades/x.x.x

    תחליף x.x.x במספר הגירסה

    כיצד מגבים את הפורום שכאמור משתמש ב- PostgreSQL?

    PGDATABASE=<db_name> PGUSER=<db_username> PGPASSWORD=<db_password> pg_dump -Fc -f <output_filename>

    תחליף כל מה שנמצא ב-<> בערכים מתאימים
    ותדביק לטרמינל ותלחץ אנטר

    תקבל קובץ גיבוי בשם <output_filename> (כלומר הערך שבחרת להכניס שם) שאפשר לשחזר אותו עם פקודת
    pg_resore במקרה הצורך

    💡 טיפ: כדאי להכניס את התאריך של היום לתוך שם הקובץ - אם זה פקודה שאתה הולך להריץ מפעם לפעם, כך תדע מאיזה תאריך הגיבוי

    ע"ע: https://www.postgresql.org/docs/current/app-pgdump.html
    או man pg_dump

  • 25 הצבעות
    3 פוסטים
    733 צפיות
    yossizY
    הטייפ השולל: never

    נחזור שוב ל-never לכמה רגעים
    הטייפ never הוא סט בלי חברים, טייפ ששום ערך לא יכול להיות בו חבר.
    נמצא שלא יקרה אף פעם שלערך אמיתי יהיה טייפ never
    אם כן לְמָה זה טייפ שימושי?

    שלילת מצב

    אחד מהשימושים של טייפ זה הוא לסמן ל-TS שמצב מסויים אמור להיות בלתי אפשרי, ולקבל אישור מ-TS שזה באמת בלתי אפשרי
    למשל: אם רוצים לוודא שב-switch עברנו על כל האפשרויות ולא פיספסנו אחד מהם בטעות אפשר לכתוב ככה:

    type Color = 'red' | 'blue' | 'green' function handleColor(color: Color) { switch (color) { case 'red': // ... break case 'blue': // ... break case 'green': // ... break default: throw new Error('Impossible!') } }

    פה אנחנו בודקים בזמן ריצה שלא הגענו לענף הבלתי אפשרי

    אבל עם TS יש לנו אפשרות לבדוק בזמן קימפול שלא שכחנו לטפל בשום אפשרות
    מוסיפים שורה זו:

    type Color = 'red' | 'blue' | 'green' function handleColor(color: Color) { switch (color) { case 'red': // ... break case 'blue': // ... break case 'green': // ... break default: const _test:never = color throw new Error('Impossible!') } }

    עיין שורה 15. אנחנו מצהירים ל-TS שבשלב הזה מיצינו את כל הערכים האפשריים ש-color יכול לקבל ופה הטייפ חייב להיות never, כלומר זה לא יקרה אף פעם
    (להבין יותר איך זה עובד, כדאי להכיר את המושג narrowing, בקיצור נמרץ: מנוע TS עוקב אחרי משתנים תוך כדי זרימת הקוד וכאשר הוא רואה ביטויים מסויימים בקוד, הוא מבין אותם ומוציא מתוך ה-union של הטייפ של המשתנים את אותם הטייפים שהקוד שולל, ובהקשר שלנו, בכל ענף של ה-switch, מנוע TS יכיר בעובדה שהטייפ של color הוא רק הערך שאותו ענף מטפל, ובענף default הטייפ הוא האפשרויות שה-switch לא מיצה)
    ברגע שנוסיף עוד אפשרות ל-union של Color נקבל מיד אזהרה שהמשתנה _test קיבל ערך שהטייפ שלו הוא לא never

    שלילת ערך

    אבל השימוש שמעניין אותנו יותר פה הוא השימוש השני,
    כאשר יוצרים טייפ חדש באמצעות ביטוי עם תנאי, ורוצים שענף אחד של התנאי לא יחזיר שום טייפ, או יותר נכון: יחזיר טייפ ריק, במקום כזה בא never לידי שימוש
    נדגים את זה על ידי ה-helper המובנה - Exclude
    (helper הוא פונקציה שעוזר לבניית טייפ שמבוסס על טייפ קיים. נזכיר: פונקציה ב-TS == ‏generic)
    הטייפ Exclude מגיע מובנה ב-TS ושימושו הוא כאשר רוצים ליצור מ-union קיים, טייפ שדומה למקור רק שחסר ממנו אחד או יותר ערכים.
    למשל:

    type Weekday = 'sunday' | 'monday' | 'tuesday' | 'wednesday' | 'thursday' | 'friday' | 'saturday' type Workday = Exclude<Weekday, 'friday' | 'saturday'>

    כפי שאפשר לראות: ה"פונקציה" Exclude מקבלת כפרמטר ראשון את הטייפ המקורי ובפרמטר השני union של טייפים (או טייפ יחיד) לחסר מהטייפ המקורי.

    איך הוא עובד?
    הנה קוד המקור

    type Exclude<T, U> = T extends U ? never : T

    להבין את זה צריך להקדים עוד דבר אחד: ביטוי של תנאי שמריצים על union עובד על כל אבר של ה-union בנפרד
    בתיעוד של TS קוראים לזה: Distributive Conditional Types
    כלומר זה עובד כמו הקוד פסואודו הבא:

    function Conditional(source: Union, condition: Type => Bool, resultIfTrue: Type => Type, resultIfFalse: Type => Type) { const runConditional = (type: Type) => { if (condition(type)) { return resultIfTrue(type) } else { return resultIfFalse(type) } } return source.split('|').map(runConditional).join('|') } function Exclude(source: Union, exclusions: Union) { return Conditional(source, t => t.extends(exclusions), t => t, t => never) } Exclude(Weekday, 'friday' | 'saturday') // 'sunday' | 'monday' | 'tuesday' | 'wednesday' | 'thursday' | never | never

    מקווה שהפסאודו קוד מובן
    רק מזכיר שוב כמה נקודות שכבר הזכרנו:

    בדיקת extends בודק עם הצד שמאלי כולו כלול בתוך הסט שהצד הימני מייצג פעולת union עם never - כמוהו כמו אי-פעולה. הוספת סט ריק לסט המקורי לא מוסיף שום דבר, לכן בתוצאה של Exclude אפשר להשמיט את ה-never בלי שום השלכה הערה בענין מילת extends

    ℹ בדרך אגב, כמה אנשים שאלו שאלה זו: למה המצב שבו טייפ אחד כלול לגמרי בתוך טייפ אחר נקרא בלע"ז extends, הרי המשמעות של extend בלע"ז הוא "הרחבה" ופה מדובר על הצרה?!
    התשובה לזה לכאורה (וכן הסכים לזה מתכנת אחר שדיבר איתי על זה) שהמילה "הרחבה" בהקשר זה לא מדבר על הסט שהוא תוצאה מהגדרת הטייפ אלא על הגדרת הטייפ עצמו,
    ככל שאתה יותר מאריך בהגדרת הטייפ, כך אתה שולל יותר ויותר מועמדים פוטנציאליים.
    לדוגמה: טייפ unknown הוא הטייפ הכי גדול מצד אחד, כי הוא כולל כל הערכים האפשריים, ומצד שני הגדרתו הוא הכי קצר: אין שום הגדרה, כל מה שזז נכנס לתוך הטייפ הזה. ברגע שמרחיבים את ההגדרה, למשל מוסיפים תנאי שיש לו מתודה פלונית, אתה מצר את מעגל החברים בטייפ

    "פונקציית" Omit

    עכשיו נוכל להסביר את הטייפ Omit שבו סיימנו את הפוסט הראשון, וזה אמור להיות מובן בקלות כעת

    הפונקציה מקבלת בפרמטר הראשונה אובייקט, ובשנייה, union של מפתחות שאתה רוצה להשמיט ממנו
    דוגמה לשימוש (מתוך התיעוד הרשמי):

    type Todo = { title: string description: string completed: boolean createdAt: number } type TodoPreview = Omit<Todo, "description">;

    ℹ שיניתי קצת מהמקור בתיעוד של TS ממילת המפתח interface למילת type רק לשם העקביות כי לא הצגנו interface במאמר זה - יש הבדל קטן בין השניים אבל זה נושא לשיחה אחרת ולא חשוב כעת
    פה אני רוצה להתמקד על האינטואיציות המרכזיות ולא על פרטים קטנים

    והנה קוד המקור של Omit

    type Omit<T, K extends keyof any> = { [P in Exclude<keyof T, K>]: T[P]; }

    ננתח את זה לחלקים:

    הפרמטרים Omit<T, K extends keyof any>

    הפונקציה מקבלת שני פרמטרים, הראשון ברור. זה יכול להיות כל טייפ שהוא. השני מוגבל לקבל רק טייפ שמקיים בעצמו התנאי extends keyof any
    מה זה keyof any? זו דרך קצרה להגיד כל טייפ שחוקי להשתמש בו כמפתח של אובייקט כלשהו, שזה כהיום: string | number | symbol. אז הפרמטר השני הוא טייפ שמורכב רק מדברים שמותרים במפתח אובייקט

    ה-body של הפונקציה { [P in Exclude<keyof T, K>]: T[P]; }

    יש פה שימוש בכמה דברים שהסברנו כבר למעלה, נתחיל מהפנים לחוץ:

    keyof T = מחזיר union של כל המפתחות של שדות בטייפ T Exclude<keyof T, K>‎ = מוציא מתוך זה את השמות של השדות שאתה רוצה להשמיט בטייפ הסופי מיפוי [P in Exclude<keyof T, K>] מריץ לולאה על כל חבר מבודד מתוך ה-union שהתקבל מהשלב הקודם כאשר הטייפ המבודד מיוצג על ידי המשתנה P { [P in Exclude<keyof T, K>]: T[P]; } = מייצג טייפ שבו עבור כל P בלולאה, יש שדה בשם P וערך מהטייפ T[P] = כלומר הטייפ המקורי של שדה זו בטייפ המקורי פסואודו קוד

    והנה פסאודו קוד לקינוח:

    function Omit(t: Type, u: UnionOfKeys) { const res = {} for (key of Omit(Keyof(t), u).split('|')) { res[key] = t[key] } return res }

    פשוט ביותר!

    הנושא המקורי (אחרי כל ההקדמות הארוכות)

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

    ולשם הקדמה אביא את הטריגר שהביא אותי להבנה זו:
    מישהו שאל: איך אפשר ליצור טייפ שבו מותרים רק שדה x ו-y ולא שום שדה נוסף

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

    type HasFoo = { foo: string }

    גם אובייקט שיש לו שדה bar יכול להיות חבר בקובצת HasFoo

    const hasBar = { bar: 1, foo: 'foo' } const test:HasFoo = hasBar // no error

    ℹ Object literal may only specify known properties
    אם הייתי כותב בקיצור בקטע הנ"ל:

    const test:HasFoo = { bar: 1, foo: 'foo' }

    הייתי מקבל שגיאה זו: Object literal may only specify known properties, and 'bar' does not exist in type 'HasFoo'.(2353)
    אל תתנו לשגיאה זו להטעות אותך! העובדה ש-HasFoo לא מצהיר על שדה bar לא מונע מחברי הסט לשאת שדות נוספות!
    ההתרעה של TS הוא מסיבה אחרת: מכיון שהמשתנה היחיד שקיבל את הערך של { bar: 1, foo: 'foo' } יש לו טייפ שלא כולל את השדה bar, יוצא שבפועל אין דרך להשתמש בשדה bar. כי הגישה דרך משתנה test אסור כי השדה לא כלול בטייפ שלו. רוב הסיכויים הם שקוד כזה הוא שגיאה של המתכנת, לכן TS מתריע.
    לעומת זאת, בדוגמה שהבאתי, ששמרתי את הערך בתוך משתנה אחר לפני ההשמה ל-test, אין על מה להתריע מכיון ששדה bar נשאר נגיש דרך משתנה hasBar

    נחזור לשאלה: איך אפשר לשלול שדות לא מוצהרות מטייפ

    ספוילר: התשובה היא שאי אפשר. וזה מתועד בתשובות ב-stack overflow ו-issues בגיטהאב

    אבל אני כעקשן ניסתי בכל זאת לפתור את זה על ידי הטייפ הבא:

    type T = { x: string y: number } type Exact<T> = { [K in keyof any]?: K extends keyof T ? T[K] : never }

    מקווה שכעת קל לכם להבין את הקוד

    בתרגום לאנגלית, זה אומר ככה:
    בטייפ Exact<T>‎: קח את הטייפ של כל מפתח חוקי אפשרי (keyof any), עבור כל חבר מתוך מרכיביו בלולאה ותבדוק אם הוא מתוך המפתחות של T, אם כן, הערך של המפתח בתוך התוצאה צריך להיות כמו ב-T (המקור); אחרת הטייפ צריך להיות never - דבר שכמובן לא יכול להיות
    לכאורה יצא לנו טייפ שאוסר מפתחות מיותרות

    התשובה היא מה שכתבתי בכותרת: "טייפ X לא זהה ל-union של כל הערכים האפשריים שהטייפ כולל"

    כלומר, הלולאה של K in keyof any שמפרק את keyof any למרכיביו, ומעביר כל מרכיב בודד בלולאה, לא מפרק את הטייפ string לכל מחרוזת אפשרית. בהקשר זה string הוא אטומי. כמו"כ number.

    היה אפשר לחשוב אחרת, כי סה"כ הטייפ string הוא סה"כ סט שמחובר מכל המחרוזות האפשריים ביקום. אבל לצערנו TS לא מסתכל על זה ככה. אלא מתייחסים ל-string כאטום. ולכן בלולאה K in keyof any יש התייחסות רק ל-string ו-number ו-symbol ולא לערכים הפרטיים שמרכיבים אותם. כמובן, אם ככה, ההמצאה שלי לא תעבוד כי התנאי K extends keyof T אף פעם לא יתקיים

    השלכה נוספת

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

    type NotWeekday = Exclude<string, Weekday>

    אנשים מצפים שדבר כזה יעבוד. אבל זה לא עובד. ולפי הנ"ל זה מובן
    נזכיר את קוד המקור של Exclude

    type Exclude<T, U> = T extends U ? never : T

    הטייפ מתבסס על העובדה שלפני בדיקת התנאי יש פירוק של T למרכיביו ובדיקת התנאי רץ על כל מרכיב בנפרד (Distributive Conditional Types)
    אבל לצערנו, הטייפ string הוא אטומי. הוא לא מתפרק לכל המחרוזות שמרכיבים אותו. לכן התנאי T extends U אף פעם לא מתקיים

    תם ולא נשלם

  • Debugging על ViewModel ב-WPF

    12
    0 הצבעות
    12 פוסטים
    596 צפיות
    קומפיונטק

    @yossiz גם אני נתקל בבעיות האלו, ולפעמים אפילו התוכנה נסגרת מבלי לציין שום exception, קשה לשחזר את זה כי זה קורה רק בפרויקטים גדולים עם קוד אסינכרוני, לדוגמא יש לי Task.Run שבתוכו יש try/catch שהוא נקרא ממתודה אסינכרונית אחרת שגם היא עוטפת אותו ב - try/catch, ואז עם כל הבלגן הזה פתאום נופלת לך שגיאה במקום לא ברור. בפרויקטים קטנים זה פשוט לא קורה.

    לפעמים אפילו vs מציב לי את השגיאה בפונקציה שמריצה את ה thread הראשי באתחול האפליקציה.

  • עזרה בביטוי רגולארי

    10
    0 הצבעות
    10 פוסטים
    483 צפיות
    dovidD

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

    דוגמה לקוד של filter_templates אחרי התיקונים הנ"ל:

    def filter_templates(string): parsed = mwparserfromhell.parse(string) for template in parsed.filter_templates(parsed.RECURSE_OTHERS): template_str = "".join([str(param) for param in template.params]) yield [str(template), template.name.strip(), template_str]

    כמו"כ כדאי להשתמש עם אובייקטים במקום מערך בתוצאה, משהו כזה:

    def filter_templates(string): parsed = mwparserfromhell.parse(string) for template in parsed.filter_templates(parsed.RECURSE_OTHERS): template_str = "".join(map(str, template.params)) yield { "template": str(template), "name": template.name.strip(), "template_str": template_str, }

    ובקוד המשתמש צריך לפנות לi["name"] במקום למיקום מספרי.

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

  • שימוש נכון ב-await Task.Run ב-C#

    7
    0 הצבעות
    7 פוסטים
    318 צפיות
    קומפיונטק

    @dovid כתב בשימוש נכון ב-await Task.Run ב-C#:

    ובCPU, צריך לעשות ממש דברים רציניים מאוד כדי שתהיה הצדקה לקפיאה.

    באפליקציה קלאסית נתקלים בזה כשמריצים סינון על הרבה פריטים באמצעות תיבת חיפוש, ולפעמים ה - UI קופא לזמן קצר, במקרה הזה הפתרון להשתמש ב - Task.Run.

    יש שני סיבות למה להשתמש בכלל בTask:
    א. לומר לתוכנה שהיא לא צריכה הרגע לחכות לתוצאה, אלא לכשתגיע נדבר.
    ב. לנצל את ריבוי המעבדים.

    הייתי מגדיר את זה טיפה שונה: המטרה העיקרית של Task ו - async/await היא לא לחסום את ה - thread הראשי. המושג הכללי multi-threading נועד גם בין היתר לנצל את ריבוי המעבדים.

  • מבנה נתונים גלובלי עבור Checked TreeView ב-Wpf

    1
    5 הצבעות
    1 פוסטים
    152 צפיות
    אין תגובות
  • נושא זה נמחק!

    11
    0 הצבעות
    11 פוסטים
    73 צפיות
בא תתחבר לדף היומי!