之前曾經在測試DLL的時候使用了PowerShell
最近剛好又翻到當時的測試檔
不過時間久了,如何執行.psl檔都沒印象了
之前曾經在測試DLL的時候使用了PowerShell
最近剛好又翻到當時的測試檔
不過時間久了,如何執行.psl檔都沒印象了
接下來要介紹winscp COM Library在excel vba的簡單使用方式
延續「Word / Command Button 無法設定文字對齊的替代方案,使用Label」
因為 Label可以控制文字置中,所以用來替代Command Button
在「Word / 使用VBA分割word內的表格」的按鈕
如果不特別設定的話,文字都會被遮蓋
也無法做任何的調整
爬文得到的解決方式
有人建議前後增加空格,或者調整字體或字型大小,因為當整體長度超過按鈕寬度就會自動置左
這種純手動,不是很方便
有人建議改用Label(標籤)
雖然少了按鈕的動態效果,但至少文字是可以完整呈現
所以我改用Label來綁定程式碼
這樣畫面感覺好多了!!
之前在「Word / 使用VBA分割word內的表格」使用VBA分割表格
現在同樣的原因需要分割審查結果的表格
表格架構都一樣,要輸出的內容架構也一樣
這次改在excel控制word物件來分割word裡的表格
這個是Line社團的提問
讓我想起之前"彰化一整天"有個類似的VBA程式
之前「網站 / 從wordpress發佈新文章同步寄信到blogger儲存成草稿」
在 wordpress網站建立觸發器,發布新文章的同時,直接將文章內容寄到blogger的自訂信箱作為草稿
曾經在 Gg / App 從Google Spreadsheets建立查詢ISBN的AppSheet APP
以及 Gg / 從Google Spreadsheets建立查詢ISBN的AppSheet APP 版本2
結合Google AppSheet簡易製作查詢ISBN App
本篇是 VBA / Excel VBA將檔案另存成PDF再使用自訂python程式加密PDF 的番外
在爬文的過程中,可能因為關鍵字的關係「 VBA PDF 加密」
所以跑出一篇在mobile01論壇的教學 使用vba + 開源函式庫,解決excel 另存pdf 無法加密問題(vba範例)
為了下載檔案而加入會員,還好檔案還在、還好不需要什麼鬼積分
依樣畫葫蘆可以得到相同結果
但是這個開源ProtectPDF.dll引起我的興趣
再次爬文之後,在這篇 VBA : encrypted / password protected PDF for MS Office
可以看到使用相同名稱的DLL
但是這篇文章的作者沒有提供ProtectPDF.dll檔案
下面有人問他 “Where is ProtectPDF.dll download site ” 也沒有得到回應
所以嘗試用dnSpy看看能不能反編譯在mobile01論壇下載的DLL,看看兩篇文章的DLL是不是一樣的
根據dnSpy的編譯結果,可以確認至少功能是一樣的
如同VBA : encrypted / password protected PDF for MS Office所提到的
這個DLL是用C#編寫的,主要是使用ITEXTSHARP.dll的功能
Rummaging through all the above to address the simple task of filling in a gap in the Word/Excel object model functionality to save an encrypted PDF and set different security options from VBA, I found that the simplest and quickest solution to make a custom COM wrapper around one of well-known .Net open source libraries. As an in house component, you shouldn’t have to worry about getting IT approval. If you not familiar with making COM visible .NET DLL, here is an attached Visual Studio 2013 .NET v 4.0 project, written in C# and wrapping a popular library ITEXTSHARP.dll which is an .NET PDF library ported from Java. For simplicity, ITEXTSHARP.dll is imbedded into single output resulting library ProtectPDF.dll with a single method GoPDF.ProtectPdfStandard(string passwordUser, string passwordOwner, string namepathPDFIn, string namepathPDFOUT )
所以嘗試改成用exe來執行程式碼
基本上就是把ProtectPdfStandard()抓出來,在main()接收參數後執行
流程:
#3 引用 iTextSharp.text.pdf
#20-23 接收命令列傳來的參數
#29 將參數傳到 自訂函數ProtectPdfStandard
#39-81 ProtectPdfStandard的內容,都是從ProtectPdfStandard()抓來的
重點是在#61-70執行iTextSharp.text.pdf的PdfReader.Encrypt方法
Program.cs程式碼如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
using System; using System.IO; using iTextSharp.text.pdf; namespace goPdf { internal class Program { static void Main(string[] args) { //Console.WriteLine($"parameter count = {args.Length}"); /* for (int i = 0; i < args.Length; i++) { Console.WriteLine($"Arg[{i}] = [{args[i]}]"); }*/ if (args.Length > 0) { // string passwordUser = args[0]; string passwordOwner = args[1]; string inputPath = args[2]; string outputPath = args[3]; //Console.WriteLine(passwordUser); //Console.WriteLine(passwordOwner); //Console.WriteLine(inputPath); //Console.WriteLine(outputPath); // string errorText = ProtectPdfStandard(passwordUser, passwordOwner, inputPath, outputPath); Console.WriteLine(errorText); // } else { Console.WriteLine("沒有輸入參數"); } } public static string ProtectPdfStandard(string passwordUser, string passwordOwner, string namepathPDFIn, string namepathPDFOUT) { string text = string.Empty; string result; if (string.IsNullOrWhiteSpace(passwordUser)) { result = "Error: User Password not set"; } else if (string.IsNullOrWhiteSpace(passwordOwner)) { result = "Error: Owner Password not set"; } else if (string.IsNullOrWhiteSpace(namepathPDFIn)) { result = "Error: User Password not set"; } else if (string.IsNullOrWhiteSpace(namepathPDFOUT)) { result = "Error: Owner Password not set"; } else { try { using (Stream stream = new FileStream(namepathPDFIn, FileMode.Open, FileAccess.Read, FileShare.Read)) { using (Stream stream2 = new FileStream(namepathPDFOUT, FileMode.Create, FileAccess.Write, FileShare.None)) { PdfReader pdfReader = new PdfReader(stream); PdfEncryptor.Encrypt(pdfReader, stream2, true, passwordUser, passwordOwner, 2564); } } } catch (Exception ex) { text = ex.Message; } result = text; } return result; } } } |
備註:ITEXTSHARP.dll是從dnSpy另存出來的
這邊的流程就大同小異,不過因為這個函數接收4個參數
passwordUser 開啟密碼
passwordOwner 編輯權限密碼
inputPath 輸入檔案路徑
outputPath 輸出檔案路徑
所以程式碼稍微修改如下
#42-57 新增了一個陣列,用來存儲輸出的檔案路徑
#72-75 設定參數,密碼的部分之後可以再視情框修改
#78 執行命令列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
Public Sub tt3() Application.DisplayAlerts = False Application.ScreenUpdating = False Dim fso As Object Set fso = CreateObject("Scripting.FileSystemObject") ActiveWorkbook.Sheets(1).Activate '目前檔案路徑 nPath = ActiveWorkbook.Path '輸出資料夾名稱 strFolderName = "output" '完整的輸出資料夾路徑 outputFolderPath = nPath & Application.PathSeparator & strFolderName & Application.PathSeparator '判斷輸出資料夾是否存在 strFolderExists = Dir(nPath & Application.PathSeparator & strFolderName, vbDirectory) If strFolderExists = "" Then '不存在則新增 fso.CreateFolder nPath & Application.PathSeparator & strFolderName Else '存在則移除 再新增 fso.DeleteFolder nPath & Application.PathSeparator & strFolderName, True 'True 強制刪除 fso.CreateFolder nPath & Application.PathSeparator & strFolderName End If '將工作表轉存為PDF檔 For i = 2 To Sheets.Count nName = Sheets(i).Name Sheets(i).Copy ActiveWorkbook.ExportAsFixedFormat Type:=xlTypePDF, Filename:=outputFolderPath & nName & ".pdf" ActiveWorkbook.Close False Next '讀取output資料夾的PDF 如果存在 回傳檔案名稱.副檔名 pdfFile = Dir(outputFolderPath & "*.pdf") Dim fileArr() As String Dim outArr() As String i = 0 Do While pdfFile <> "" ReDim Preserve fileArr(i) ReDim Preserve outArr(i) fileArr(i) = outputFolderPath & pdfFile 'Debug.Print outputFolderPath & pdfFile outArr(i) = outputFolderPath & Split(pdfFile, ".")(0) & "_PW.pdf" 'Debug.Print outputFolderPath & Split(pdfFile, ".")(0) & "_PW.pdf" i = i + 1 pdfFile = Dir() Loop 'Debug.Print fileArr(0) '陣列上限(序位值) num = UBound(fileArr) Dim wsh As Object Set wsh = VBA.CreateObject("WScript.Shell") Dim waitOnReturn As Boolean: waitOnReturn = True Dim windowStyle As Integer: windowStyle = 0 Dim errorCode As Long For i = 0 To num DoEvents passwordUser = "123" passwordOwner = "456" inputPath = fileArr(i) outputPath = outArr(i) '透過WScript.Shell 執行pdf加密程式 s = Chr(34) & Excel.ActiveWorkbook.Path & "\C#\goPDF\" & "goPDF.exe" & Chr(34) & Chr(32) & Chr(34) & passwordUser & Chr(34) & Chr(32) & Chr(34) & passwordOwner & Chr(34) & Chr(32) & Chr(34) & inputPath & Chr(34) & Chr(32) & Chr(34) & outputPath & Chr(34) ' Debug.Print s Shell s errorCode = wsh.Run(s, windowStyle, waitOnReturn) If errorCode = 0 Then ' MsgBox "Done! No error to report." Debug.Print "輸出:" & fileArr(i) & Chr(32) & "到:" & outArr(i) Else MsgBox "Program exited with error code " & errorCode & "." End If Next Application.DisplayAlerts = True Application.ScreenUpdating = True End Sub |
由於google正式關閉了 https://chart.googleapis.com
在 Py / 透過selenium-webdriver爬youtube的介紹資訊(2021/10/28修改)
所引用的selenium-webdriver 在更新之後,目前selenium版本是4.19.0
聽說網站如果能夠具備多語系內容
可以更容易被搜尋到
但是我又不會多語
之前網站因為增加了許多自訂的發文推播
導致網站速度變慢,GCP的VM觀測數據顯示發文的時候,CPU的執行率可以達到200%
所以也出現提升CPU等級的建議,但是往上升一級就多了近一倍的費用
對我來說實在吃不消,因為除了GCP的費用之外,還有youtube的月費、google 雲端硬碟的年費
一年付給google公司7~8千元跑不掉,GCP費用占了80%
當初建置網站的目的是為了紀錄一些學習程式的過程,順便紀錄自己感興趣的東西
所以想先試試看能不能透過一些方式來降低網站的執行負荷量
臉書只能夠用分享的方式將訊息貼到個人頁面於是,開始思考如何在Blogger達成這個效果
google blogger可以接收電子郵件來發佈文章
1 2 3 |
For Each a In ActiveSheet.Shapes If a.Type = msoPicture Then a.Delete Next |
1 2 3 |
For Each a In ActiveSheet.Shapes If a.Type = msoPicture Or a.Type = msoLinkedPicture Then a.Delete Next |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
With Sheets("清冊") lRow = .[b65536].End(xlUp).Row For I = 2 To lRow On Error Resume Next 'strFile = ThisWorkbook.Path & "\" & .Cells(i, 4) & ".jpg" strFile = ActiveWorkbook.Path & "\" & .Cells(I, 2) & ".jpg" Set oPic = .Pictures.Insert(strFile) With .Cells(I, 3) oPic.Top = .Top oPic.Left = .Left oPic.Width = 60 oPic.Height = 70 End With Set oPic = Nothing Next I End With |
1 2 3 4 5 6 7 8 9 10 11 |
With Sheets("清冊") lRow = .[b65536].End(xlUp).Row For I = 2 To lRow On Error Resume Next 'strFile = ThisWorkbook.Path & "\" & .Cells(i, 4) & ".jpg" ' strFile = "C:\Users\trico\Pictures" & "\" & .Cells(I, 2) & ".jpg" strFile = ActiveWorkbook.Path & "\" & .Cells(I, 2) & ".jpg" Set oPic = .Shapes.AddPicture(strFile, msoFalse, msoTrue, Cells(I, 3).Left + 2, Cells(I, 3).Top + 1, 120, 70) Set oPic = Nothing Next I End With |