मैं एक एक्सेल टेबल (लिस्टोबजेक्ट) के माध्यम से एक वीबीए for each
लूप चला रहा हूं जो जांचता है कि किसी दिए गए पथ के आधार पर कोई फ़ाइल मौजूद है या नहीं। हालांकि मेरी तालिका का विस्तार हुआ है और इसमें 68K लिस्ट्रो हैं। कोड लॉन्च करने के बाद, यह जल्दी से एक त्रुटि देता है Run-time-error '7': Out of memory
यह 63 के लाइनों (5 मिनट के भीतर किया गया) के साथ ठीक चलता है और गुगलिंग के आधार पर "64 के सेगमेंट सीमा" नामक कुछ प्रतीत होता है। क्या यह मेरे कोड को चलाने के लिए प्रभावित कर रहा है क्योंकि यह वास्तव में ऐसा लगता है कि यह पहली बार पंक्ति गणना को बफर करता है और फिर वास्तव में कुछ भी चलाने के लिए शुरू होता है। क्या मेरे डेटासेट को कई बैचों में विभाजित करने की आवश्यकता के बिना इसके लिए कोई आसान समाधान है? सच कहूं, तो मैं काफी हैरान था कि 2021 में एक्सेल में 64K की सीमा अभी भी एक चीज होगी।
इसे 64 बिट एक्सेल 2019 पर चलाना, लेकिन Office365 के साथ भी कोई भाग्य नहीं।
Sub CheckFiles()
Dim Headers As ListObject
Dim lstrw As ListRow
Dim strFileName As String
Dim strFileExists As String
Application.ScreenUpdating = False
Set ws = ThisWorkbook.Sheets("Import")
Set Headers = ws.ListObjects("Import")
For Each lstrw In Headers.ListRows
strFileName = lstrw.Range(7)
strFileExists = Dir(strFileName)
If strFileExists = "" Then
lstrw.Range(4) = "not found"
Else
lstrw.Range(4) = "exists"
End If
Next lstrw
Set ws = Nothing
Set Headers = Nothing
Application.ScreenUpdating = True
End Sub
2 जवाब
वर्कशीट तक पहुँचने से बचें
- चूंकि आप लूपिंग से बच नहीं सकते हैं, आप इसे कंप्यूटर की मेमोरी में बेहतर तरीके से करते हैं, यानी किसी श्रेणी के सेल के बजाय किसी सरणी के तत्वों के माध्यम से।
- कोड अभी भी धीमा है, मेरी मशीन पर 200k पंक्तियों के लिए लगभग 10s, लेकिन यह
Dir
के कारण है। - ध्यान दें कि यह कितना आसान है (केवल एक पंक्ति, जब श्रेणी में एक से अधिक सेल होते हैं) और एक सरणी (
Data = rg.Value
) में एक श्रेणी लिखना (प्रतिलिपि बनाना) कितना तेज़ (एक विभाजित सेकंड) है और लिखना (प्रतिलिपि बनाना) है एक श्रेणी में वापस सरणी (rg.Value = Data
)। - स्थिरांक अनुभाग में मानों को समायोजित करें।
Option Explicit
Sub CheckFiles()
Const wsName As String = "Import" ' Worksheet Name
Const tblName As String = "Import" ' Table Name
Const cCol As Long = 7 ' Criteria Column
Const dCol As Long = 4 ' Destination Column
Dim wb As Workbook: Set wb = ThisWorkbook
Dim ws As Worksheet: Set ws = wb.Worksheets(wsName)
Dim Headers As ListObject: Set Headers = ws.ListObjects(tblName)
Dim Data As Variant ' Data Array
With Headers.ListColumns(cCol).DataBodyRange
If .Rows.Count = 1 Then
ReDim Data(1 To 1, 1 To 1): Data = .Value
Else
Data = .Value
End If
End With
Dim r As Long ' Array Row Counter (DataBodyRange Row Counter)
Dim FileName As String ' File Name Retrieved by Dir
For r = 1 To UBound(Data, 1)
FileName = Dir(CStr(Data(r, 1)))
If Len(FileName) = 0 Then
Data(r, 1) = "not found"
Else
Data(r, 1) = "exists"
End If
Next r
Headers.ListColumns(dCol).DataBodyRange.Value = Data
End Sub
आप सभी को धन्यवाद! कुछ टेकअवे। स्पष्ट रूप से यथासंभव कुशल कोड लिखने की कोशिश करते हुए, यहां कोई भी उचित प्रदर्शन स्वीकार्य है। इसके साथ ही, for each
लूप ने 63K लाइनों के साथ चलने में लगभग 5 मिनट का समय लिया, जबकि यह लगभग 15 सेकंड में उस कोड द्वारा किया गया था जिसे मैंने @ VBasic2008 द्वारा उत्तर के रूप में स्वीकार किया था - बिना क्षमता की समस्याओं के भी।
इस विशेष कोड के साथ मेरी एकमात्र समस्या यह थी कि यह मेरे लिए कुछ नया दृष्टिकोण था, इसलिए संभवतः भविष्य में इस पर निर्माण करने के लिए इसमें गहराई से देखने के लिए कुछ समर्पण की आवश्यकता है - लेकिन यह निश्चित रूप से कुशल दिखता है। मैंने एक नियमित for ... to
लूप भी एक साथ रखा जो 68K लाइनों के साथ समस्याओं में नहीं चलता था और offset
फ़ंक्शन के साथ पंक्तियों और स्तंभों के बीच चलता था।
स्पष्ट रूप से for each
से तेज @Pᴇʜ के रूप में सुझाव दिया लेकिन सरणी विधि (30 सेकंड या तो) के रूप में लगभग 2x लंबा लगा।
Sub CheckFiles_2()
Dim strFileName, strFileExists As String
Dim ws As Worksheet
Dim Headers As ListObject
Dim result As String
Dim counter, RowCount As Long
Application.ScreenUpdating = False
Set ws = ThisWorkbook.Sheets("Import")
Set Headers = ws.ListObjects("Import")
RowCount = Headers.ListRows.Count
For counter = 1 To RowCount
strFileName = Range("anchorCell").Offset(counter, 3)
strFileExists = Dir(strFileName)
If strFileExists = "" Then
result = "not found"
Else
result = "exists"
End If
Range("anchorCell").Offset(counter, 0) = result
Next counter
Set ws = Nothing
Set Headers = Nothing
Application.ScreenUpdating = True
End Sub
संबंधित सवाल
नए सवाल
excel
केवल एक्सेल ऑब्जेक्ट्स या फ़ाइलों, या जटिल फॉर्मूला विकास के खिलाफ प्रोग्रामिंग पर प्रश्नों के लिए। यदि आप लागू हो तो आप Excel टैग को VBA, VSTO, C #, VB.NET, PowerShell, OLE स्वचालन और अन्य प्रोग्रामिंग संबंधी टैग और प्रश्नों के साथ जोड़ सकते हैं। सुपर उपयोगकर्ता पर एकल कार्यपत्रक कार्यों के लिए एमएस एक्सेल के बारे में सामान्य सहायता उपलब्ध है।