<a href="https://www.explainxkcd.com/wiki/index.php/1319:_Automation">xkcd Automation</a>

عندما تكون عملية إرسال التقريرات، أو الحسابات أمراً متكرراً يومياً، يمكن أن تكون الحاجة إلى أتمتة ذلك أمراً مفضلاً.

سأكتب هنا برنامجاً صغيراً أستخدمه لفتح ملف Excel واستخلاص بعض القيم من خلايا معينة، ثم إرسال التقريرات بالبريد، وتحضيرها لإرسالها باستخدام تطبيق Whtsapp Web من متصفح الإنترنت اختيارياً.

فتح ملف Microsoft Excel والتعامل معه

نستخدم (COM Component لفتح ملف الـExcel

EnglishToArabicDayNameName(DayNameName) {
  if (DayName = "Saturday") {
    return "السبت"
  }
  else if (DayName = "Sunday")
  {
    return "الأحد"
  }
  else if (DayName = "Monday")
  {
    return "الإثنين"
  }
  else if (DayName = "Tuesday")
  {
    return "الثلاثاء"
  }
  else if (DayName = "Wednesday")
  {
    return "الأربعاء"
  }
  else if (DayName = "Thursday")
  {
    return "الخميس"
  }
  else if (DayName = "Friday")
  {
    return "الجمعة"
  }
  else {
    return
  }
}

GetReportsFromExcel() {
  NowDate := A_Now
  NowDate += -1, d  ; التاريخ سيكون عن اليوم السابق باعتبار التقرير يرسل في اليوم التالي

  FormatTime Day, %NowDate%, dddd
  FormatTime Date, %NowDate%, d-M-yyyy

  Day = EnglishToArabicDayName(Day)

  FilePath = %A_MyDocuments%\MyReport.xlsm

  IfNotExist, %A_MyDocuments%\MyReport.xlsm
  {
    MsgBox,16, خطأ,  الملف المطلوب:`n%FilePath%`nغير موجود.
    Exit, 1
  }

  SetFormat, float, 2.2

  oWorkbook := ComObjGet(FilePath)			;فتح ملف الـExcel

  TextHeader = %Day% %Date%`n

  ; قراءة قيمة نص من مستند جديد في برنامج Notepad++ لاستعماله في بعض الحسابات
  ControlGetText, ValueToCalculate, Scintilla1, ahk_class Notepad++
  if (ErrorLevel)
  {
    MsgBox,16,خطأ, حدث خطأ أثناء قراءة النص.
    Exit, 1
  }

  if (ValueToCalculate <= 0 or ValueToCalculate is not number)
  {
    MsgBox,16,خطأ, الرقم المدخل أصغر من صفر أو ليس رقماً.
    Exit, 1
  }

  Sellings = % oWorkbook.Sheets("Sheet1").Range("H4").Value
  if (Sellings <= 0 or Sellings is not number)
  {
    MsgBox,16,خطأ,  المبيعات عدد غير صحيح، راجع القيمة المدخلة في ملف الـExcel؛ خلية H4.
    Exit, 1
  }

  Average := (Sellings/ValueToCalculate)
  TextAverage=%TextAverage%+متوسط سعر إجمالي مبيعات الصنف %ValueToCalculate%وحدة/%Average%`n`n

  MorningSellings = % oWorkbook.Sheets("Sheet1").Range("B13").Value
  MorningCash = % oWorkbook.Sheets("Sheet1").Range("B19").Value

  if (MorningSellings >= 0 and MorningSellings is number and MorningCash >= 0 and MorningCash is number)
  {
    MorningText=الصندوق: %MorningCash%`nالجرد: %MorningSellings%`n
  }

  NightSellings = % oWorkbook.Sheets("Sheet1").Range("E13").Value
  NightCash = % oWorkbook.Sheets("Sheet1").Range("E19").Value

  if (NightSellings >= 0 and NightSellings is number and NightCash >= 0 and NightCash is number)
  {
    NightText=الصندوق: %NightCash%`nالجرد: %NightSellings%`n`n
  }

  if (MorningText and NightText)
  {
    TextSellings=الصباح:`n%MorningText%`nالمساء:`n%NightText%
  }
  else if (MorningText)
  {
    TextSellings=%MorningText%`n
  }
  else if (NightText)
  {
    TextSellings=%NightText%
  }

  GeneralSellings = % oWorkbook.Sheets("Sheet1").Range("H14").Value
  if (GeneralSellings <= 0 or GeneralSellings is not number)
  {
    MsgBox,16,خطأ, مجموع المبيعات العام عدد غير صحيح، راجع القيمة المدخلة في الملف؛ خلية H14.
    Exit, 1
  }
  else
  {
    TextSellings=%TextSellings%+المبيعات: %GeneralSellings%
  }

  Text := TextAverage . TextSellings

  oWorkbook.Close()
  Process, Close, EXCEL.exe

  ; كتابة نص التقرير في المستند في برنامج Notepad++
  ControlSetText, Scintilla1, Text, ahk_class Notepad++
}  

إرسال بريد باستخدام بروتوكول SMTP

سنقوم باستخدام COM Component البريد لإرسال بريد عن طريق مخدم SMTP كذلك لاحظ أن البرنامج أدناه لا ينسخ الرسالة إلى مجلّد البريد المرسَل لذلك لن تجدها هناك.

SendEmail()
{
  If !(f:=FileOpen(A_MyDocuments . "\MyReport.xlsm","r-rwd"))
  {
    MsgBox, 16, خطأ, لا يمكن إرفاق الملف للبريد.
    return
  }
  else
    f.close()

  Date := A_Now
  Date += -1, d  ; التاريخ سيكون عن اليوم السابق باعتبار التقرير يرسل في اليوم التالي

  FormatTime Date, %Date%, d/M/yyyy

  pmsg := ComObjCreate("CDO.Message")
  pmsg.From := """aborazmeh"" <mymail@aboraz.me>" ; عنوان بريد المرسِل
  pmsg.To := "recipient@myjob.co"                 ; عنوان بريد المرسَل إليه
  pmsg.Subject := "التقرير اليومي الآلي " . Date   ; عنوان الرسالة
  sAttach   		:= A_MyDocuments . "\MyReport.xlsm|" ; يمكن إدراج عدة ملفات يفصل بينها بـ |
  fields := Object()
  fields.smtpserver := "smtp.aboraz.me" ; عنوان مخدم إرسال البريد SMTP
  fields.smtpserverport     := 465      ; منفذ مخدم الإرسال 465 الافتراضي الآمن، أو 25 من غير SSL
  fields.smtpusessl      := True        ; استخدام طبقة بروتوكول SSL الآمن
  fields.sendusing     := 2             ; إرسال باستخدام المنفذ المذكور
  fields.smtpauthenticate     := 1      ; المصادقة باستخدام اسم المستخدم وكلمة المرور
  fields.sendusername := "mymail@aboraz.me" ; اسم المستخدم
  fields.sendpassword := "MySecretPassw0rd" ; كلمة المرور
  fields.smtpconnectiontimeout := 60

  schema := "http://schemas.microsoft.com/cdo/configuration/"

  pfld :=   pmsg.Configuration.Fields

  For field,value in fields
      pfld.Item(schema . field) := value
  pfld.Update()

  Loop, Parse, sAttach, |, %A_Space%%A_Tab%
    pmsg.AddAttachment(A_LoopField)

  pmsg.Send()

  TrayTip, رسالة, تم إرسال البريد بنجاح, 5

  return 1
}

إرسال تقرير عبر تطبيق Whatsapp

WhatsappSend(Text1, Text2)
{
  BlockInput, On                ; منع المستخدم من الإدخال لحماية تسلسل الأوامر

  Sleep, 3000                   ; الانتظار ثلاث ثوانٍ قبل العملية التالية
  SendInput {Tab}               ; أول ضغطة لمفتاح الجدولة ستنقل التحكم إلى مربع البحث

  Sleep, 3000
  ; اسم المجموعة / المستقبل الذي سنبحث عنه
  SendInput, مجموعة التقارير

  Sleep, 3000
  SendInput, {Tab}{Enter}       ; نقرة أخرى لمفتاح الجدولة، ثم مفتاح الإدخال ستنقل التحكم إلى كتابة الرسالة
  Sleep, 3000

  ; تجهيز النص للإدخال
  StringReplace, Text1, Text1, `n, +{enter}, All
  StringReplace, Text2, Text2, `n, +{enter}, All

  ; مسح جميع المدخلات في مربع كتابة الرسالة ثم إدخال أول نص، ثم الثاني وإرسال كلاً منهما
  SendInput, {Home}{Shift down}{End}{Shift up}{Delete}%Text1%{enter}%Text2%{enter}

  BlockInput, Off ; إعادة التحكم إلى المستخدم
}

جميع ما تقدّم في ملف واحد

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

#NoEnv
#Persistent
SendMode Input
SetWorkingDir %A_ScriptDir%
CoordMode, Mouse, Screen

Include email.ahk
#Include whatsapp.ahk

Menu, TRAY, Add
Menu, TRAY, Add, مساعدة, HelpMenuHandler, +Right
Menu, TRAY, Add, عن البرنامج.., AboutMenuHandler
Return

; يمكن إضافة رسالة مساعدة عند النقر على أيقونة البرنامج المصغرة
HelpMenuHandler:
Return

; قائمة عن البرنامج عند النقر على أيقونة البرنامج المصغرة
AboutMenuHandler:
  FormatTime, CurrentYear, , yyyy
  MsgBox, 1577024, Created by aborazmeh 2015-%CurrentYear%©.
Return

+!^q::ExitApp

; عند الضغط على Shift+Ctrl+e في برنامج Notepad++ سيقوم بأخذ ما كُتب ويقرأ مستند Excel ويحسب النتيجة ثم يستبدل ما كُتب في Notepad++ بالنص المطلوب
#IfWinActive ahk_class Notepad++
+^e::
  GetReportsFromExcel()

  if (SendEmail())
	; فتح برنامج Firefox يجب تعديل المسار إذا لم يتطابق على نظام آخر
	; ولكن يجب تغيير MozillaWindowClass و ahk_exe firefox عند تغيير البرنامج ذاته
    Run, C:\Program Files (x86)\Mozilla Firefox\firefox.exe http://web.whatsapp.com
Return

; عند ضغط Ctrl+Alt+w في نافذة Firefox سيقول بالبحث عن المرسل إليه وإرسال الرسالة عبر Whatsapp
#IfWinActive ahk_class MozillaWindowClass ahk_exe firefox.exe
!^w::
  WhatsappSend(TextTakseera, TextSellings)
return