การลบไฟล์ใน VBA


คำตอบ:


168

1. ) ตรวจสอบที่นี่ โดยทั่วไปทำสิ่งนี้:

Function FileExists(ByVal FileToTest As String) As Boolean
   FileExists = (Dir(FileToTest) <> "")
End Function

ฉันจะปล่อยให้คุณพิจารณาการจัดการข้อผิดพลาดต่างๆที่จำเป็น แต่สิ่งเหล่านี้เป็นหนึ่งในข้อผิดพลาดในการจัดการสิ่งที่ฉันกำลังพิจารณา:

  • ตรวจสอบสตริงว่างที่กำลังส่ง
  • ตรวจสอบสตริงที่มีอักขระที่ผิดกฎหมายในชื่อไฟล์ / เส้นทาง

2. ) วิธีการลบไฟล์ ดูที่นี่ โดยทั่วไปใช้คำสั่ง Kill แต่คุณต้องอนุญาตให้มีความเป็นไปได้ที่ไฟล์จะเป็นแบบอ่านอย่างเดียว นี่คือฟังก์ชั่นสำหรับคุณ:

Sub DeleteFile(ByVal FileToDelete As String)
   If FileExists(FileToDelete) Then 'See above          
      ' First remove readonly attribute, if set
      SetAttr FileToDelete, vbNormal          
      ' Then delete the file
      Kill FileToDelete
   End If
End Sub

อีกครั้งฉันจะปล่อยให้คุณจัดการข้อผิดพลาดและสิ่งเหล่านี้คือสิ่งที่ฉันพิจารณาอีกครั้ง:

  • สิ่งนี้ควรทำงานแตกต่างกันไปสำหรับไดเร็กทอรีกับไฟล์หรือไม่? ผู้ใช้ควรต้องระบุอย่างชัดเจนว่าต้องการลบไดเร็กทอรีหรือไม่?

  • คุณต้องการให้รหัสรีเซ็ตแอตทริบิวต์แบบอ่านอย่างเดียวโดยอัตโนมัติหรือผู้ใช้ควรได้รับการบ่งชี้บางอย่างว่ามีการตั้งค่าแอตทริบิวต์แบบอ่านอย่างเดียวหรือไม่?


แก้ไข: ทำเครื่องหมายคำตอบนี้เป็นวิกิชุมชนเพื่อให้ทุกคนสามารถแก้ไขได้หากจำเป็น


ขอบคุณ - จะเกิดอะไรขึ้นถ้ามีสองไฟล์ที่มีชื่อเดียวกันซึ่งมีอยู่ไฟล์ย่อย DeleteFile จะฆ่าทั้งสองไฟล์หรือเพียงไฟล์เดียว? คำแนะนำใด ๆ ที่ชื่นชมมาก
BKSpurgeon

6
คุณไม่สามารถมีสองไฟล์ที่มีชื่อเดียวกันในไดเร็กทอรี
Onorio Catenacci

53

อีกวิธีหนึ่งในการเขียนโค้ดคำตอบของ Brettski ซึ่งฉันเห็นด้วยทั้งหมดอาจเป็น

With New FileSystemObject
    If .FileExists(yourFilePath) Then
        .DeleteFile yourFilepath
    End If
End With

เอฟเฟกต์เดียวกัน แต่มีการประกาศตัวแปรน้อยกว่า (ดีไม่มีเลย)

FileSystemObject เป็นเครื่องมือที่มีประโยชน์จริงๆและคุ้มค่าที่จะได้เป็นมิตรกับ นอกเหนือจากสิ่งอื่นใดสำหรับการเขียนไฟล์ข้อความบางครั้งอาจเร็วกว่าทางเลือกเดิมซึ่งอาจทำให้บางคนประหลาดใจ (จากประสบการณ์ของฉันอย่างน้อย YMMV)


7
การใช้ไวยากรณ์นี้โดยไม่ต้องประกาศอ็อบเจ็กต์สคริปต์ไฟล์ต้องเพิ่มการอ้างอิงสำหรับ Microsoft Scripting Runtime อื่น ๆ : Dim fs As New Scripting
FileSystemObject

5
คุณต้องอ้างอิงไลบรารีสคริปต์ด้วย ดูที่นี่: stackoverflow.com/questions/3233203/…
ekkis

เนื่องจากไม่มีตัวแปรให้ตั้งค่าเป็น Nothing จึงมีความเสี่ยงที่ FileSystemObject จะยังคงอยู่ในหน่วยความจำทำให้เกิดการรั่วไหลหรือปัญหาอื่น ๆ หรือไม่?
johny why

ไม่ได้จะถูกยกเลิกหลังจาก "สิ้นสุดด้วย" เนื่องจากไม่ได้กำหนดให้กับตัวแปรผลจะคล้ายกับวัตถุที่กำหนดให้กับตัวแปรที่ตั้งค่าเป็น "Nothing"
jony

15

ฉันอาจจะได้รับความเดือดร้อนจากสิ่งนี้ แต่จุดทดสอบการดำรงอยู่คืออะไรถ้าคุณจะลบมัน? หนึ่งในสัตว์เลี้ยงตัวหลักของฉันคือแอปที่ส่งกล่องโต้ตอบข้อผิดพลาดบางอย่างเช่น "ไม่สามารถลบไฟล์ได้ไม่มีอยู่จริง!"

On Error Resume Next
aFile = "c:\file_to_delete.txt"
Kill aFile
On Error Goto 0
return Len(Dir$(aFile)) > 0 ' Make sure it actually got deleted.

ถ้าไฟล์ไม่มีตั้งแต่แรกภารกิจก็สำเร็จ!


4
คุณยกประเด็นที่ดี แต่ฉันคิดว่ามันขึ้นอยู่กับบริบทและบางครั้งการมีฟังก์ชัน "File Exists" ก็มีประโยชน์นอกเหนือจากการลบ
Onorio Catenacci

3
+1: บางทีผู้ใช้แอปพลิเคชันอาจต้องการถูกถามก่อนที่จะลบไฟล์ตัวอย่างเช่นการใช้ActiveWorkbook.SaveCopyAsไม่สามารถเขียนทับได้ดังนั้นคุณต้องลบไฟล์ที่มีอยู่ซึ่งมีชื่อไฟล์เดียวกันก่อน
Joël

แต่คุณไม่ควรใช้ไม่On Error Resume Nextเช่นนั้นฉันก็บอกแล้ว: D แน่นอนนั่นเป็นคำแนะนำที่ไร้สาระและคำตอบของคุณก็ถูกต้อง
johny why

Len(dir(...))ส่วนหนึ่งไม่ได้เป็น แต่เพียงผู้เดียวในการตรวจสอบสำหรับการดำรงอยู่ นอกจากนี้ยังมีการตรวจสอบหากไฟล์ที่ถูกซ่อนไว้เนื่องจากไฟล์ที่ซ่อนอยู่จะกลับเป็นสตริงว่างถึงแม้ว่ามันจะมีอยู่ Dir(hiddenFile) = ""(และคุณจะไม่สามารถที่จะลบมัน): ดังนั้นส่วนSetAttr FileToDelete, vbNormalนี้ดูแลอย่างดีสำหรับคุณ
elektrykalAJ

11

สิ่งต่อไปนี้สามารถใช้เพื่อทดสอบการมีอยู่ของไฟล์จากนั้นจึงจะลบออก

Dim aFile As String
aFile = "c:\file_to_delete.txt"
If Len(Dir$(aFile)) > 0 Then
     Kill aFile
End If 

3
ฉันรู้ว่าคำถามและคำตอบนี้เก่าเพียงแค่คิดว่าฉันจะเพิ่มว่าการใช้ Len () เพื่อทดสอบสตริง (และฟังก์ชันที่ส่งคืนสตริง) ดูเหมือนจะเร็วกว่าการเปรียบเทียบสตริงตามตัวอักษรใน VBA
JimmyPena

7
เหตุผลที่Len()(และLenB()ซึ่งเร็วกว่า) เร็วกว่าการเปรียบเทียบสตริงก็คือในหน่วยความจำสตริง VB จะนำหน้าด้วยความยาว Len / LenB เพียงแค่ดึงความยาวจากตำแหน่งหน่วยความจำนั้นพวกเขาไม่จำเป็นต้องวนซ้ำผ่านสตริงเพื่อให้ทราบความยาว ในทางกลับกันการใช้การเปรียบเทียบสตริงมีงานที่ต้องทำมากขึ้น นอกจากนี้หลีกเลี่ยงการใช้""ใน VB เนื่องจากจะจัดสรรสตริงใหม่เสมอ ใช้vbNullStringแทนเนื่องจากเป็นค่าคงที่และไม่ใช้หน่วยความจำเพิ่มเติม
มองซิเออร์บอมปุส

7

ใน VB โดยปกติDirจะค้นหาไดเร็กทอรีของไฟล์ หากไม่ว่างเปล่าแสดงว่ามีอยู่แล้วใช้Killเพื่อกำจัดไฟล์

test = Dir(Filename)
If Not test = "" Then
    Kill (Filename)
End If

6

ตั้งค่าการอ้างอิงไปยังไลบรารี Scripting.Runtimeจากนั้นใช้ FileSystemObject:

Dim fso as New FileSystemObject, aFile as File

if (fso.FileExists("PathToFile")) then
    aFile = fso.GetFile("PathToFile")
    aFile.Delete
End if

ฉันใช้เมธอด FileSystemObject ด้วยเนื่องจาก Kill ไม่สามารถลบไฟล์ / โฟลเดอร์ที่มี diacritis ได้
mauek unak

นี่เป็นวิธีที่ฉันใช้ .. ผู้ที่ใช้สิ่งนี้ต้องการใช้การตรวจสอบข้อผิดพลาดและ DisplayAlerts = false (ไฟล์จะไม่ลบหากมีการใช้งานดังนั้นต้องมี error trap)
Gregg Burns

3

นี่คือเคล็ดลับ: คุณกำลังใช้ชื่อไฟล์ซ้ำหรือวางแผนที่จะทำอะไรบางอย่างที่ต้องลบทันที?

ไม่มี?

คุณสามารถรับ VBA เพื่อเริ่มคำสั่ง DEL "C: \ TEMP \ scratchpad.txt" / F จากพรอมต์คำสั่งแบบอะซิงโครนัสโดยใช้ VBA.Shell:

เชลล์ "DEL" & chr (34) & strPath & chr (34) & "/ F", vbHide

สังเกตเครื่องหมายอัญประกาศคู่ (อักขระ ASCII 34) รอบ ๆ ชื่อไฟล์: ฉันสมมติว่าคุณมีเส้นทางเครือข่ายหรือชื่อไฟล์แบบยาวที่มีช่องว่าง

หากเป็นไฟล์ขนาดใหญ่หรืออยู่ในการเชื่อมต่อเครือข่ายที่ช้าการใช้ไฟและการลืมคือวิธีที่ต้องทำ แน่นอนคุณไม่เคยเห็นว่ามันได้ผลหรือไม่ แต่คุณกลับมาใช้งาน VBA ต่อทันทีและมีบางครั้งที่ดีกว่ารอเครือข่าย


นี่เป็นทางเลือกที่ดีหาก asynch คือสิ่งที่คุณต้องการ
johny why

2

คุณสามารถตั้งค่าการอ้างอิงไปยังไลบรารี Scripting.Runtime จากนั้นใช้ FileSystemObject มีเมธอด DeleteFile และเมธอด FileExists

ดูบทความ MSDN ที่นี่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.