Home » excel » powershell – Creating a new excel worksheet via .Copy() and moving it to the last position

powershell – Creating a new excel worksheet via .Copy() and moving it to the last position

Posted by: admin March 7, 2020 Leave a comment

Questions:

I’ve been at this for quite a while,

I want to create a new worksheet by copying another. This places the new sheet before the sheet being copied. I then want to move it to the very end of all of the sheets.

The aim is to have worksheets called > summary1 > summary2 > summary3 .. etc in that order

Here is what I have (excuse brevity)

$ex = New-Object -ComObject Excel.Application
$ex.Visible = $true
$wb = $ex.Workbooks.Add()

for ($i = 1; $i -le 3; $i++)
{
    $wb.Worksheets.Item(2).Copy($wb.Worksheets.Item(2))
    $newSheet = $wb.Worksheets.Item(2)
    $newSheet.Activate()
    $name = "Summary$i"
    $newSheet.Name = $name
    $wb.Worksheets.Item($name).Move($wb.Worksheets.Item($i + 1))        
}

It works for the first sheet, it renames the sheet then moves it to the end but after that everytime it reaches the .Move method it doesn’t do anything except .Activate() the original “Summary” sheet.

I have no idea how to explain this behaviour.. Thankyou kindly in advance.

Edit: Changed $wb.Worksheets.Item(“Summary”).Move to $wb.Worksheets.Item($name).Move

Edit:

Here is the solution:

for ($i = 1; $i -le 3; $i++)
{
    $wb.Worksheets.Item(2).Copy($wb.Worksheets.Item(2))
    $newSheet = $wb.Worksheets.Item(2)
    $newSheet.Activate()
    $name = "Summary$i"
    $newSheet.Name = $name

    $lastSheet = $wb.WorkSheets.Item($wb.WorkSheets.Count) 
    $newSheet.Move([System.Reflection.Missing]::Value, $lastSheet)      
}
How to&Answers:

Marked as Community because it is from the question above.

Here is the solution:

for ($i = 1; $i -le 3; $i++)
{
    $wb.Worksheets.Item(2).Copy($wb.Worksheets.Item(2))
    $newSheet = $wb.Worksheets.Item(2)
    $newSheet.Activate()
    $name = "Summary$i"
    $newSheet.Name = $name

    $lastSheet = $wb.WorkSheets.Item($wb.WorkSheets.Count) 
    $newSheet.Move([System.Reflection.Missing]::Value, $lastSheet)      
}

Answer:

I can propose a more “general” and possibly quicker answer, just for the sake of having it. Just have in mind that it is from VBA and will need minor modifications to run in same environment as your question.

Sub sheetCopier()
    Dim destSht As Object, srcSht As Object, NewShts As Long, shtCnt As Long

    Set srcSht = ThisWorkbook.Sheets(2)

    For NewShts = 1 To 5
        shtCnt = ThisWorkbook.Sheets.Count
        srcSht.Copy after:=ThisWorkbook.Sheets(shtCnt)
        Set destSht = ThisWorkbook.Sheets(shtCnt + 1)
        destSht.Name = "New Sht" & Format(NewShts, "00")
    Next
    Set srcSht = Nothing
    Set destSht = Nothing

End Sub

obviously what may interest you are:

shtCnt = ThisWorkbook.Sheets.Count
srcSht.Copy after:=ThisWorkbook.Sheets(shtCnt)
Set destSht = ThisWorkbook.Sheets(shtCnt + 1)
destSht.Name = "New Sht" & Format(NewShts, "00")

and the rest are just to make a running demo.

you could make things with even less code, but it is not so nice:

thisworkbook.sheets(2).Copy after:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count)
ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count).Name = "New Sht" & Format(NewShts, "00")

so i guess (but can’t confirm) your code could be written like:

for ($i = 1; $i -le 3; $i++)
{
    $wb.Worksheets(2).Copy(,$wb.Worksheets($wb.Worksheets.count))
    $name = "Summary$i"
    $wb.Worksheets($wb.Worksheets.count).Name = $name
}

just notice that copy syntax is: .copy([before],[after]) with both before and after optionals. In vba the ways to set after would be: .copy after:=ASheetObject or .copy ,aSheetObject

cheers