How do you create an Outlook Appointment / Meeting in PowerShell?
The following code will create an Outlook Appointment in PowerShell.
Function Create-Appointment(){
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)][String]$Subject,
[Parameter(Mandatory=$true)][DateTime]$MeetingStart,
[Parameter()][String]$Recipients,
[Parameter()][String]$Categories,
[Parameter()][String]$Location,
[Parameter()][String]$Body=$Subject,
[Parameter()][int]$ReminderMinutesBeforeStart=15,
[Parameter()][int]$DurationInMinutes=30
)
$ol = New-Object -ComObject Outlook.Application
$meeting = $ol.CreateItem('olAppointmentItem')
if($ReminderMinutesBeforeStart -gt 0){
$meeting.ReminderSet = $true
$meeting.ReminderMinutesBeforeStart = $ReminderMinutesBeforeStart
}
if($PSBoundParameters.ContainsKey('Recipients')){
foreach($email in $Recipients -split ";"){
if($email -ne ''){
$meeting.Recipients.Add($email)
}
}
$meeting.MeetingStatus = [Microsoft.Office.Interop.Outlook.OlMeetingStatus]::olMeeting
} else {
$meeting.MeetingStatus = [Microsoft.Office.Interop.Outlook.OlMeetingStatus]::olNonMeeting
}
if($PSBoundParameters.ContainsKey('Location')){
$meeting.Location = $Location
}
if($PSBoundParameters.ContainsKey('Categories')){
$meeting.Categories = $Categories
}
$meeting.Subject = $Subject
$meeting.Body = $Body
$meeting.Start = $MeetingStart
$meeting.Duration = $DurationInMinutes
$meeting.Save()
$meeting.Send()
}
Related
I already have a working snippet for stamping PDF's.
But, now a request has reached me for adding an additional page to the same document.
I have managed to get it working, but I'd like to verify that it is the best way to do it.
Edit: It turns out it is not working as expected.
The fields get malformatted with a big "x" instead of the text as per below image. If I click the field I can see that the text has been input though.
Old code
$FieldsHash = ConvertFrom-StringData -StringData $Fields
$FieldsHash | Export-Clixml C:\Temp\fieldhash.xml
$reader = New-Object iTextSharp.text.pdf.PdfReader -ArgumentList $InputPdfFilePath
$stamper = New-Object iTextSharp.text.pdf.PdfStamper($reader, [System.IO.File]::Create($OutputPdfFilePath))
foreach ($j in $FieldsHash.GetEnumerator())
{
try {
$formattedDate = Get-Date $j.Value -Format $DatePattern
$null = $stamper.AcroFields.SetField($j.Key, $formattedDate)
}
catch {
try {
$null = $stamper.AcroFields.SetField($j.Key, $j.Value)
} catch {
"Could not find $($j.Key)"
}
}
}
$stamper.Close()
Modified code:
$fileStream = New-Object System.IO.FileStream($OutputPdfFilePath, [System.IO.FileMode]::OpenOrCreate)
$document = New-Object iTextSharp.text.Document
$pdfCopy = New-Object iTextSharp.text.pdf.PdfCopy($document, $fileStream)
$mainreader = New-Object iTextSharp.text.pdf.PdfReader($InputPdfFilePath)
$stamper = New-Object iTextSharp.text.pdf.PdfStamper($mainreader, $fileStream)
$document.Open()
$FieldsHash = ConvertFrom-StringData -StringData $Fields
$FieldsHash | Export-Clixml C:\Temp\pdf\fieldhash.xml
foreach ($j in $FieldsHash.GetEnumerator())
{
try {
$formattedDate = Get-Date $j.Value -Format $DatePattern
$null = $stamper.AcroFields.SetField($j.Key, $formattedDate)
} catch {
try {
$null = $stamper.AcroFields.SetField($j.Key, $j.Value)
} catch {
"Could not find $($j.Key)"
}
}
}
$pdfCopy.AddDocument($mainreader)
$mainreader.Dispose()
$attreader = New-Object iTextSharp.text.pdf.PdfReader($att)
$pdfCopy.AddDocument($attreader)
$attreader.Dispose()
$pdfCopy.Dispose()
$document.Dispose()
$fileStream.Dispose()
Solution, user stamper methods instead:
$reader = New-Object iTextSharp.text.pdf.PdfReader -ArgumentList $InputPdfFilePath
$stamper = New-Object iTextSharp.text.pdf.PdfStamper($reader, [System.IO.File]::Create($OutputPdfFilePath))
foreach ($j in $FieldsHash.GetEnumerator())
{
try {
$formattedDate = Get-Date $j.Value -Format $DatePattern
$null = $stamper.AcroFields.SetField($j.Key, $formattedDate)
} catch {
try {
$null = $stamper.AcroFields.SetField($j.Key, $j.Value)
} catch {
"Could not find $($j.Key)"
}
}
}
if(Test-Path $attpath) {
$attreader = New-Object iTextSharp.text.pdf.PdfReader($attpath)
$stamper.InsertPage(3,$attreader.GetPageSize(1))
$stamper.replacePage($attreader, 1, 3)
$stamper.Close()
$reader.Close()
$attreader.Close()
}
else {
$stamper.Close()
$reader.Close()
}
I want to create a PowerShell based GUI with windows forms to display items in different containers and enable the user to drag items (control objects) from one container to another. Because of some bad flickering I copied the answer from this question and converted the code into PowerShell:
How to double buffer .NET controls on a form?
The problem is, that the objects are "smearing" on the form when I start dragging them and I can't find how to solve this.
class Dictionary : System.Collections.DictionaryBase
{
Dictionary() {}
[Bool]Exists([System.Object] $Key) {return ($Key -in $this.Keys) }
}
function SetDoubleBuffered()
{
param([System.Windows.Forms.Control] $TargetControl)
[System.Reflection.PropertyInfo] $DoubleBufferedProp = [System.Windows.Forms.Control].GetProperty("DoubleBuffered", [System.Reflection.BindingFlags]::NonPublic -bor [System.Reflection.BindingFlags]::Instance)
$DoubleBufferedProp.SetValue($TargetControl, $True, $Null)
}
function Button_MouseDown()
{
[CmdletBinding()]
param(
[parameter(Mandatory=$True)][System.Object] $Sender,
[parameter(Mandatory=$True)][System.EventArgs] $EventArguments
)
$Sender.Tag.DragStart = $False
$Sender.Tag.StartX = $EventArguments.X
$Sender.Tag.StartY = $EventArguments.Y
}
function Button_MouseUp()
{
[CmdletBinding()]
param(
[parameter(Mandatory=$True)][System.Object] $Sender,
[parameter(Mandatory=$True)][System.EventArgs] $EventArguments
)
$Sender.Tag.DragStart = $False
$Sender.Tag.StartX = 0
$Sender.Tag.StartY = 0
}
function Button_MouseMove()
{
[CmdletBinding()]
param(
[parameter(Mandatory=$True)][System.Object] $Sender,
[parameter(Mandatory=$True)][System.EventArgs] $EventArguments
)
if ($EventArguments.Button.value__ -gt 0)
{
if (-not $Sender.Tag.DragStart)
{
if ([System.Math]::sqrt([System.Math]::Pow($Sender.Tag.StartX - $EventArguments.X, 2) + [System.Math]::Pow($Sender.Tag.StartY - $EventArguments.Y, 2)) -ge 10)
{
$Sender.Tag.DragStart = $true
}
}
else
{
$Sender.Left = $Sender.Left + ($EventArguments.X - $Sender.Tag.StartX)
$Sender.Top = $Sender.Top + ($EventArguments.Y - $Sender.Tag.StartY)
}
}
else
{
$Sender.Tag.DragStart = $False
$Sender.Tag.StartX = 0
$Sender.Tag.StartY = 0
}
}
function OpenForm()
{
$Form = [System.Windows.Forms.Form]::new()
$Form.Text = "DragTest"
$Form.Width = 900
$Form.Height = 900
$Button = [System.Windows.Forms.Button]::new()
$Button.Left = 10
$Button.Top = 30
$Button.Height = 20
$Button.Width = 100
$Button.Text = "MyButton"
$Button.Name = "SomeButton"
$Button.Tag = [Dictionary]::new()
$Button.Add_MouseDown({Button_MouseDown -Sender $Button -EventArguments $_})
$Button.Add_MouseUp({Button_MouseUp -Sender $Button -EventArguments $_})
$Button.Add_MouseMove({Button_MouseMove -Sender $Button -EventArguments $_})
$Form.Controls.Add($Button)
SetDoubleBuffered -TargetControl $Form
SetDoubleBuffered -TargetControl $Button
$Form.ShowDialog() | Out-Null
}
cls
OpenForm
I have created a script that must select all the items in a powershell form, based on a variable. If the variable $bolCheckAllNumberedItems has the value '$False, then the grid should not be selected, in case the variable $bolCheckAllNumberedItems has the value '$True', the whole grid should be selected.
The code I have:
Clear-Host
$bolCheckAllNumberedItems = $True
$frmTest = New-Object 'System.Windows.Forms.Form'
$btnOk = New-Object 'System.Windows.Forms.Button'
$chkAllItems = New-Object 'System.Windows.Forms.CheckBox'
$DataGridForTest = New-Object 'System.Windows.Forms.DataGridView'
$InitialFormWindowState = New-Object 'System.Windows.Forms.FormWindowState'
$frmTest.Controls.Add($btnOk)
$frmTest.Controls.Add($chkAllItems)
$frmTest.Controls.Add($DataGridForTest)
$frmTest.AutoScaleDimensions = New-Object System.Drawing.SizeF(6, 13)
$frmTest.AutoScaleMode = 'Font'
$frmTest.ClientSize = New-Object System.Drawing.Size(284, 261)
$frmTest.Name = 'frmTest'
$frmTest.StartPosition = 'CenterScreen'
$frmTest.Text = 'Test'
#
# btnOk
#
$btnOk.Location = New-Object System.Drawing.Point(186, 220)
$btnOk.Name = 'btnOk'
$btnOk.Size = New-Object System.Drawing.Size(75, 23)
$btnOk.TabIndex = 1
$btnOk.Text = '&Ok'
$btnOk.UseVisualStyleBackColor = $True
$btnOk.add_Click($btnOk_Click)
#
# chkAllItems
#
$chkAllItems.Location = New-Object System.Drawing.Point(22, 22)
$chkAllItems.Name = 'chkAllItems'
$chkAllItems.Size = New-Object System.Drawing.Size(104, 24)
$chkAllItems.TabIndex = 1
$chkAllItems.Text = 'Select all items'
$chkAllItems.UseVisualStyleBackColor = $True
$chkAllItems.add_CheckedChanged($chkAllItems_CheckedChanged)
#
# DataGridForTest
#
$DataGridForTest.ColumnHeadersHeightSizeMode = 'AutoSize'
$DataGridForTest.Location = New-Object System.Drawing.Point(22, 52)
$DataGridForTest.Name = 'DataGridForTest'
$DataGridForTest.Size = New-Object System.Drawing.Size(240, 150)
$DataGridForTest.TabIndex = 0
$DataGridForTest.TabStop = $False
$DataGridForTest.ColumnCount = 1
$DataGridForTest.ColumnHeadersVisible = $true
$DataGridForTest.Columns[0].Name = "Number"
$DataGridForTest.Columns[0].width = 100
$DataGridForTest.ScrollBars = 'Vertical'
$DataGridForTest.ReadOnly = $True
$DataGridForTest.AllowUserToAddRows = $False
$DataGridForTest.AllowUserToDeleteRows = $False
$DataGridForTest.AllowUserToResizeColumns = $False
$DataGridForTest.AllowUserToResizeRows = $False
$DataGridForTest.SelectionMode = "FullRowSelect"
$DataGridForTest.MultiSelect = $true
#----------------------------------------------
$ArrayNumbers = #("one","two","three","for","five","six","seven","eight","nine","ten")
[system.collections.arraylist]$ArrayWithHeader = #()
ForEach ($object in $ArrayNumbers)
{
$value = [pscustomobject]#{'Number' = $object}
$ArrayWithHeader.Add($value) | Out-Null
$value = $null
}
$ArrayWithHeader | foreach {$DataGridForTest.Rows.Add($_."Number") | Out-Null }
if($bolCheckAllNumberedItems)
{
$chkAllItems.Checked = $true
$DataGridForTest.SelectAll()
}
$chkAllItems.Add_Click({
if($chkAllItems.Checked)
{
$DataGridForTest.SelectAll()
}
else
{
$DataGridForTest.ClearSelection()
}
})
$btnOk.add_Click({$frmTest.Close()})
[void]$frmTest.ShowDialog()
What is wrong with my code? Help is appreciated and with kind regards,
The Sting Pilot
I think the easiest way of doing this is to start your script with a small function you can call inside the checkbox Click() event aswell as in an added form event called Add_Shown()
function Select-Grid ([bool]$selectAll) {
$chkAllItems.Checked = $selectAll
if ($selectAll) {
$DataGridForTest.SelectAll()
}
else {
$DataGridForTest.ClearSelection()
}
}
This way you can remove these lines:
if($bolCheckAllNumberedItems)
{
$chkAllItems.Checked = $true
$DataGridForTest.SelectAll()
}
and instead write
# call the helper function with the Checked value of the $chkAllItems checkbox
$chkAllItems.Add_Click({ Select-Grid $chkAllItems.Checked })
# this is an added event that fires when the form is first shown
$frmTest.Add_Shown( { Select-Grid $bolCheckAllNumberedItems } )
[void]$frmTest.ShowDialog()
# very important! dispose of the form when you are finished with it
$frmTest.Dispose()
An alternative approach is to again remove these lines:
if($bolCheckAllNumberedItems)
{
$chkAllItems.Checked = $true
$DataGridForTest.SelectAll()
}
and change the event $chkAllItems.Add_Click() to use a different event:
$chkAllItems.Add_CheckedChanged({
if($chkAllItems.Checked) {
$DataGridForTest.SelectAll()
}
else {
$DataGridForTest.ClearSelection()
}
})
Activate that event when the form is first shown and finish the code:
$frmTest.Add_Shown( { $chkAllItems.Checked = $bolCheckAllNumberedItems } )
[void]$frmTest.ShowDialog()
# and not forget to get rid of the form from memory
$frmTest.Dispose()
Using the CheckedChanged() method does not need an extra helper function as with the first approach.
i want to replace a string with an hyperlink
i try with something like this
Update:
$FindText = "[E-mail]"
$email ="asdadasd#asdada.com"
$a=$objSelection.Find.Execute($FindText)
$newaddress = $objSelection.Hyperlinks.Add($objSelection.Range,$email) )
but this insert the email at beginnig of file word don't replace the string "[E-mail]"
Add-Type -AssemblyName "Microsoft.Office.Interop.Word"
$wdunits = "Microsoft.Office.Interop.Word.wdunits" -as [type]
$objWord = New-Object -ComObject Word.Application
$objWord.Visible = $false
$findText = "[E-mail]"
$emailAddress = "someemail#example.com"
$mailTo = "mailto:"+$emailAddress
$objDoc = $objWord.Documents.Open("Path\to\input.docx")
$saveAs = "Path\to\output.docx")
$range = $objDoc.Content
$null = $range.movestart($wdunits::wdword,$range.start)
$objSelection = $objWord.Selection
$matchCase = $false
$matchWholeWord = $true
$matchWildcards = $false
$matchSoundsLike = $false
$matchAllWordForms = $false
$forward = $true
$wrap = 1
$format = $False
$wdReplaceNone = 0
$wdFindContinue = 1
$wdReplaceAll = 2
$wordFound = $range.find.execute($findText,$matchCase,$matchWholeWord,$matchWildCards,$matchSoundsLike,$matchAllWordForms,$forward,$wrap)
if($wordFound)
{
if ($range.style.namelocal -eq "normal")
{
$null = $objDoc.Hyperlinks.Add($range,$mailTo,$null,$null,$emailAddress)
}
}
$objDoc.SaveAs($saveAs)
$objDoc.Close()
$objWord.Quit()
Remove-Variable -Name objWord
[gc]::Collect()
[gc]::WaitForPendingFinalizers()
Kinda ugly, but this script will do what you need. It loads the .docx specified with $objDoc, finds all instances of $findText, and replaces it with a mailto link for $emailAddress and then saves the changes to $saveAs.
Most of this based on a "Hey, Scripting Guy" Article
I have a function Add-TextBox, which creates a TextBox control, and assigns a block to it's event handler.
The problem I am facing is that the block is presumably being called with global namespace, and the variables declared inside the Add-TextBox function aren't accessible to it. How do I make them accessible?
Edit: added full code
Add-Type -AssemblyName System.Windows.Forms
Function Add-Control() {
Param (
[System.Windows.Forms.Form]$Form,
[string]$ControlType,
[System.Windows.Forms.Control]$AfterControl = $null,
[int]$Padding = 0
)
$control = New-Object System.Windows.Forms.$ControlType
$control.AutoSize = $true
$x = 5
$y = 5
if ($AfterControl) {
$y = $AfterControl.Location.Y + $AfterControl.Size.Height + $Padding
}
$control.Location = "5,$y"
$form.Controls.Add($control)
return $control
}
Function Add-TextBox() {
Param (
[System.Windows.Forms.Form]$Form,
[string]$Placeholder = "",
[System.Windows.Forms.Control]$AfterControl = $null,
[int]$Padding = 0
)
$control = Add-Control -Form $Form -ControlType "TextBox" -AfterControl $AfterControl -Padding $Padding
$control.Add_GotFocus({
Write-Host "Placeholder is null: $($Placeholder -eq $null)"
if ($this.Text -eq $Placeholder) {
$this.ForeColor = "Black"
$this.Text = ""
}
})
$control.Add_LostFocus({
if ($this.Text -eq "") {
$this.ForeColor = "Darkgray"
$this.Text = $Placeholder
}
})
return $control
}
$form = New-Object system.Windows.Forms.Form
$textbox = Add-TextBox -Form $form -Placeholder "(XXXXXX, npr. 012345)"
$form.ShowDialog()
Seems I can use .GetNewClosure() on script blocks to capture the local variables and retain them.
Add-Type -AssemblyName System.Windows.Forms
Function Add-Control() {
Param (
[System.Windows.Forms.Form]$Form,
[string]$ControlType,
[System.Windows.Forms.Control]$AfterControl = $null,
[int]$Padding = 0
)
$control = New-Object System.Windows.Forms.$ControlType
$control.AutoSize = $true
$x = 5
$y = 5
if ($AfterControl) {
$y = $AfterControl.Location.Y + $AfterControl.Size.Height + $Padding
}
$control.Location = "5,$y"
$form.Controls.Add($control)
return $control
}
Function Add-TextBox() {
Param (
[System.Windows.Forms.Form]$Form,
[string]$Placeholder = "",
[System.Windows.Forms.Control]$AfterControl = $null,
[int]$Padding = 0
)
$control = Add-Control -Form $Form -ControlType "TextBox" -AfterControl $AfterControl -Padding $Padding
$control.Add_GotFocus({
if ($this.Text -eq $Placeholder) {
$this.ForeColor = "Black"
$this.Text = ""
}
}.GetNewClosure()) # Here...
$control.Add_LostFocus({
if ($this.Text -eq "") {
$this.ForeColor = "Darkgray"
$this.Text = $Placeholder
}
}.GetNewClosure()) # And here.
return $control
}
$form = New-Object system.Windows.Forms.Form
$textbox = Add-TextBox -Form $form -Placeholder "(XXXXXX, npr. 012345)"
$form.ShowDialog()