วันพฤหัสบดีที่ 28 ตุลาคม พ.ศ. 2553

Microsoft Office : Word เลขไทย



ถ้าเรามีเอกสาร Microsoft Word Document (.doc, .docx) ที่สร้างไว้แล้ว โดยใช้ตัวเลขแบบอารบิก 0123456789 แต่ต้องการแปลงเป็นตัวเลขภาษาไทย ๐๑๒๓๔๕๖๗๘๙ มีวิธีช่วยให้ทำได้แบบง่ายๆ บ้างไหม?
แวบแรกที่มักคิดถึงกันก็คือความสามารถ Find / Replace ใน Word เอง กำหนดเลข ๑ แทนให้กับ 1 ไล่ไปเรื่อยจนครบ

จะให้เร็วอีกนิดก็คือบันทึกเป็น Macro ให้ค้นหาและแทนที่ทั้งหมด จากการค้นข้อมูลเรื่อง Unicode พบว่า ค่าแบบเลขทศนิยมเป็นดังนี้

อารบิก 0-9 => Unicode 48-57
ไทย ๐-๙ => Unicode 3664-3673

จึงเป็นตัวหลักที่จะเอามาใช้ใน VBA ที่จะเป็นแมโคร Word

ด้วยโค้ดดังนี้

Sub ThaiNumbers()
For i = 0 To 9
' This macro is developed by S.Chatchawal.
' schatchawal@gmail.com
' Convert Arabic Numbers To Thai Numbers
' 01234567890
' arabic 0-9 => Unicode 48-57
' Thai 0-9 => Unicode 3664-3673
Selection.HomeKey Unit:=wdStory
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting
With Selection.Find
.Text = ChrW(48 + i)
.Replacement.Text = ChrW(3664 + i)
.Wrap = wdFindContinue
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
Selection.Find.Execute Replace:=wdReplaceAll
Next
End Sub

หรือจะอีเมลมารับไฟล์ ThaiNumber.bas ไปใช้เลยก็ได้
ซึ่งจะแนบรายละเอียดไว้ในไฟล์ PDF วิธีใช้สำหรับ Word 2010 ให้ด้วย

หลังจากสร้างแมโครนี้เสร็จ การใช้ก็เพียงแต่กดคีย์ Alt+F8 เปิดไดอะล็อก Macro ขึ้น แล้วเลือกที่ Module1.ThaiNumber แล้วคลิก Run เพียงเท่านี้ทั้งเอกสารก็จะแทนที่เลขอารบิกด้วยเลขไทยแล้ว



ส่วนการเปลี่ยนตัวเลขของ Numbering หรือลำดับหัวข้อย่อย
จะใช้วิธีสร้างแมโครกับส่วนที่เลือกก็ได้ วิธีเปลี่ยนแบบหนึ่งที่สามารถทำได้ มีขั้นตอนดังนี้
1. เลือกข้อความส่วนลำดับหัวข้อย่อย

2.คลิกขวาเลือก Numbering

3.คลิกรูปแบบตัวเลขไทย

4.ตัวอย่างผลลัพธ์ที่ได้

วันอาทิตย์ที่ 24 ตุลาคม พ.ศ. 2553

AutoCAD Tips: Visual LISP ( AutoLISP ) เรื่องของการแบ่งครึ่ง

ตำแหน่งกึ่งกลางบนเส้นตรง
เป็นที่ทราบกันดีว่าใช้ Object snap ที่ Midpoint

ตำแหน่งกึ่งกลางระหว่าง 2 จุด หาได้อย่างไร
พิมพ์ MTP หรือ M2P ในพรอมต์ถามจุด และคลิกเลือก 2 จุด จะได้การวางตำแหน่งที่จุดกึ่งกลางระหว่าง 2 จุดที่เลือก เช่น มีเส้นตรงหรือเส้นโค้งที่เป็นคู่ขนานกันอยู่ จะสร้างเส้นระหว่างกลาง ให้ใช้คำสั่ง OFFSET ตัวเลือก Through เลือกเส้นต้นฉบับที่มีอยู่เส้นใดเส้นหนึ่ง พิมพ์ M2P กด Enter จับจุดด้วย Osnap | Nearest บนเส้นแรก และจับจุดด้วย Osnap | Perpendicular บนเส้นที่สอง

หรือจะประยุกต์ใช้ MTP/M2P กับการวาดรูเจาะระหว่างกึ่งกลางรูเจาะสองรูที่มีอยู่ก่อนแล้ว ก็จะเป็นไปในทำนองเดียวกัน โดยใช้คำสั่ง Circle ที่พรอมต์ถามจุดศูนย์กลาง พิมพ์ M2P กด Enter แล้วคลิกเลือกจุดศูนย์กลางของวงกลมที่มีอยู่แล้ว โดยจับจุดด้วย Osnap | Center ตามด้วยการป้อนค่ารัศมีหรือเส้นผ่านศูนย์กลาง

แบ่งครึ่งมุม
ขณะที่เรื่องของการแบ่งครึ่งบนเส้นตรงหรือระหว่างสองจุดใดๆจะถูกกล่าวถึงค่อนข้างแพร่หลาย แต่ถ้าเป็นการแบ่งครึ่งมุม (Angle Bisect) จะมีคำตอบให้หรือไม่?


จริงๆแล้วใน AutoCAD มีคำสั่งจัดการเรื่องแบ่งครึ่งมุมให้โดยตรงอยู่แล้ว นั่นคือ XLINE ที่ตัวเลือก Bisect นั่นเอง มีพรอมต์ตามรูปนี้


กล่าวคือ ให้กำหนดจุดยอดมุม (vertex) ตามด้วยจุดบนแขนเส้นตรงสองเส้น เพียงเท่านี้ก็จะได้เส้นที่มีความยาวเป็นอนันต์ (infinity) ของ XLINE แล้ว และยังคงให้เลือกมุมอื่นๆได้อีก จนกว่าจะกด Enter เพื่อจบคำสั่งนี้
เคล็ดลับ กรณีเส้นไม่บรรจบกันเป็นมุม
ให้เปิดใช้ AutoSnap ที่ตัวเลือก Extension เอาไว้ แล้วลากแนวออกมาจากเส้นทั้งสอง จะได้จุดตัดกันเป็นจุดยอดมุม (vertex)


ปิดท้ายบทความนี้ ด้วยเครื่องมือทุ่นแรง อีกสักนิด
นั่นคือโค้ด LISP สำหรับหาเส้นแบ่งครึ่งมุม โดยใช้ได้กับเส้นตรง (LINE) และเส้นโพลีไลน์ (POLYLINE)

มีพรอมต์เป็น

Command: พิมพ์ b กด Enter
Developed by schatchawal@gmail.com
Select first line (near the corner): คลิกเส้นแรกที่ใกล้มุม
Select second line: คลิกเส้นที่สอง

เพียงเท่านี้ คำสั่ง b หรือ abisect นี้ก็จะวาดเส้นแบ่งครึ่งมุมให้


เส้นแบ่งครึ่งมุมนี้มีความยาวเท่ากับเส้นแรกที่ถูกเลือก

ส่วนโค้ดมีดังนี้

;;; Angle Bisector
(defun c:b () (c:abisect) (princ))
;; (1select "\nSelect first line (near the corner): "
;; (list "AcDbLine" "AcDbPolyline")
;; "\nMust be LINE or LWPOLYLINE!!!")
(defun 1select (msg obj_type_list err_msg / e1 obj1 stop)
(while (not stop)
(if (setq e1 (entsel msg))
(progn
(setq obj1 (vlax-ename->vla-object (car e1)))
(if (member (vla-get-ObjectName obj1)
obj_type_list
)
(setq stop T)
(princ err_msg)
)
)
(princ "\nNo object found!!!")
)
)
e1
)
;; 1vector of P to Q point.
(defun 1vectorPQ (P Q / u d)
(if (not (zerop (setq d (distance P Q))))
(mapcar '(lambda (x)
(/ x d)
)
(mapcar '- Q P)
)
nil
)
)
;;Main version
(defun c:abisect (/ e1 e2 obj1 p11 p12 p21
p22 ip mp objType1 1u 1v
w 1w d param d1 d2 LL
*acaddoc* *mspace* *error*
)
(vl-load-com)
(princ "\nDeveloped by schatchawal@gmail.com")
(setq *acaddoc* (vla-get-activedocument (vlax-get-acad-object))
*mspace* (vla-get-modelspace *acaddoc*)
)
(defun *error* (msg)
(if (not (member msg (list "Function cancelled")))
(princ (strcat "\nBISECT Error: " msg))
)
(vla-endundomark *acaddoc*)
(princ)
)
(vla-startundomark *acaddoc*)
(setq e1
(1select "\nSelect first line (near the corner): "
(list "AcDbLine" "AcDbPolyline")
"\nMust be LINE or LWPOLYLINE!!!"
)
e2
(1select "\nSelect second line: "
(list "AcDbLine" "AcDbPolyline")
"\nMust be LINE or LWPOLYLINE!!!"
)
p11 (osnap (cadr e1) "Nearest")
p12 (osnap (cadr e1) "End")
p21 (osnap (cadr e2) "Nearest")
p22 (osnap (cadr e2) "End")
obj1 (vlax-ename->vla-object (car e1))
objType1 (vla-get-objectName obj1)
)
(if (setq ip (inters p11 p12 p21 p22 nil))
(progn
(cond
((equal objType1 "AcDbLine")
(setq LL (vla-get-Length obj1))
)
((equal objType1 "AcDbPolyline")
(setq
param
(fix (vlax-curve-getParamAtPoint
obj1
(vlax-curve-getClosestpointTo obj1 (trans p11 1 0))
)
)
D1
(vlax-curve-getDistAtParam obj1 param)
D2
(vlax-curve-getDistAtParam obj1 (1+ param))
LL
(abs (- D2 D1))
)
)
) ;cond
;; Find MP with plus 2 vectors
(if (and (setq 1u (1vectorPQ (trans ip 1 0) (trans p11 1 0)))
(setq 1v (1vectorPQ (trans ip 1 0) (trans p21 1 0)))
)
(progn
(setq
w (mapcar '+ 1u 1v)
d (sqrt (apply '+ (mapcar '* w w)))
1w (mapcar '/ (mapcar '/ w (list d d d)))
mp (mapcar '+
(trans ip 1 0)
(mapcar '* 1w (list LL LL LL))
)
)
;; Draw Bi-sect Line
(vla-addLine
*mspace*
(vlax-3d-point (trans ip 1 0))
(vlax-3d-point mp)
)
)
(princ "\nCannot process!!!")
)
)
(princ "\nNo intersection!!!")
)
(vla-endundomark *acaddoc*)
(princ)
)

********************************************
ส่วนการแบ่งพื้นที่ให้รูปทรงใดๆแม้ว่าจะเป็น Irregular shape อะไรก็ตาม
ลองใช้คำสั่ง DIVA จากหัวข้อนี้
http://chatchawalsupakasem.blogspot.com/2010/06/visual-lisp-autocad-tips.html
http://chatchawalsupakasem.blogspot.com/2010/06/visual-lisp-autocad-tips-diva.html

วันอังคารที่ 5 ตุลาคม พ.ศ. 2553

Photoshop Tips: ปรับภาพให้อาคารอยู่ในแนวตั้ง



วันนี้เข้าไปอ่านเว็บ PANTIP เห็นกระทู้ของท่านหนึ่ง ถามเรื่องการปรับภาพจากที่ถ่ายมาแล้วได้ภาพอาคารเอียงให้กลับมาแสดงแนวตั้งตรง มีวิธีง่ายๆอย่างไรบ้าง?

ก่อนอื่นต้องขออนุญาตเจ้าของกระทู้นำมาตอบวิธีตรงนี้นะครับ เพราะว่าผมไม่ได้เป็นสมาชิกเว็บจึงโพสต์ภาพประกอบไม่ได้

วิธีนี้แก้ไขได้ใน Photoshop ทำได้ง่ายไม่ซับซ้อนเลย มีขั้นตอนดังนี้

1. เปิดภาพขึ้นในโปรแกรม Photoshop
2. กด Ctrl+A เพื่อเลือกภาพทั้งหมด
3. กด Ctrl+Shift+J เพื่อตัดย้ายภาพนี้ไปเลเยอร์ใหม่
4. ถ้ายังไม่เห็นแนวเส้นไม้บรรทัดให้เลือกเมนู View | Rulers
ลากเส้นไกด์โดยคลิกในแนวไม้บรรทัดทางซ้าย
กดปุ่มเมาส์ค้างไว้ และลากออกมา เมื่อแนวเส้นนี้ตัดกับจุดฐานตึก
ที่เสมือนว่าจะเป็นจุดหมุนของเรา แล้วปล่อยการกดปุ่มเมาส์
ขั้นตอนนี้กะคร่าวๆ เอาไว้เป็นเส้นอ้างอิงเท่านั้น
*** ถ้าวางผิด ก็เลือกเมนู View | Clear guide แล้วลองทำใหม่
5. กด Ctrl+T เพื่อปรับเปลี่ยนรูปทรง
6. เลื่อนตัวชี้ของเมาส์ให้อยู่ในภาพ แล้วคลิกด้วยปุ่มขวาของเมาส์ และเลือก Perspective

7. วางตัวชี้ของเมาส์ที่มุมบนซ้าย แล้วลากออกไป สังเกตภาพตึกด้วย
ให้ลากไปจนได้แนวตึกตั้งตรงตามเส้นไกด์จากข้อ 4 เมื่อได้แนวที่ต้องการแล้วปล่อยการกดปุ่มเมาส์

8.กด Enter
9.กด Ctrl+E เพื่อรวมเลเยอร์กลับคืน
10. มีเทคนิคแถมอีกนิดหน่อย ภาพดูค่อนข้างครึ้มๆ ถ้าอยากได้แบบท้องฟ้าแจ่มใสอีกนิด ให้เลือกเมนู Image | Adjustments | Shadows and Highlights ยังไม่ต้องปรับค่าอะไรเลย ภาพก็ดูสว่างไสว ท้องฟ้าโปร่งขึ้นทันตาเลย จะลองปรับตามตัวเลือกที่มีดูบ้างก็ได้
11. เมื่อทั้งหมดเป็นแบบที่ต้องการแล้ว กด Ctrl+S บันทึกไฟล์

เสร็จแล้ว ...

หมายเหตุ: จะเอาเส้นไกด์ตามข้อ 4 ออกไป ให้เลือกเมนู View | Clear guides