2009-01-09 12 views
11

के छोटे सबसेट की आउटपुट फ़ाइल बनाएं, मेरे पास पाठ के 1.2 मिलियन रिकॉर्ड की एक सीएसवी फ़ाइल है। अल्फान्यूमेरिक फ़ील्ड उद्धरण चिह्नों में लिपटे हैं, दिनांक/समय या संख्यात्मक फ़ील्ड नहीं हैं।बहुत बड़ी सीएसवी पढ़ने के लिए एक्सेल में वीबीए चाहते हैं और सीएसवी

उदाहरण के लिए "फ्रेड", "स्मिथ", 01/07/1967,2, "7, हाई स्ट्रीट", "Anytown", "Anycounty", "LS1 7AA"

मैं क्या चाहता हूँ एक्सेल में कुछ वीबीए लिखें (मेरे लिए उपलब्ध एकमात्र टूल केवल इतना ही कम है कि मैं उपयोग में काफी कुशल हूं) जो रिकॉर्ड द्वारा सीएसवी रिकॉर्ड पढ़ता है, एक चेक करता है (जैसा कि यह अंतिम क्षेत्र पर होता है, पोस्ट कोड) और फिर 1.2 एम रिकॉर्ड के एक छोटे से सबसेट को एक नई आउटपुट फ़ाइल में आउटपुट करता है।

मैं समझता हूँ कि कैसे दो फ़ाइलें खोलने के लिए, रिकॉर्ड पढ़ा, मैं डेटा के साथ क्या है और इसे बाहर लिखने की ज़रूरत क्या कर

(मैं सिर्फ उत्पादन होगा एक उपसर्ग एक अपवाद प्रकार को दर्शाता है इनपुट रिकॉर्ड) मुझे नहीं पता कि वीबीए में सीएसवी को सही तरीके से कैसे पार्स करना है। मैं एक साधारण पाठ स्कैन नहीं कर सकता और अल्पविरामों की खोज करता हूं क्योंकि टेक्स्ट में कभी-कभी कॉमा होता है (इसलिए टेक्स्ट फ़ील्ड्स टेक्स्ट को सीमित क्यों किया जाता है)

क्या कोई शानदार आदेश है जो मुझे जल्दी से डेटा प्राप्त करने देता है मेरे रिकॉर्ड में क्षेत्र?

मैं क्या चाहता हूँ s_work = क्षेत्र है (s_input_record, 5) जहां 5 मेरी सीएसवी में क्षेत्र संख्या ....

बहुत धन्यवाद, सी

उत्तर

6

कैसे VBScript के बारे में है, हालांकि यह होगा है भी Excel में काम करते हैं:

Set cn = CreateObject("ADODB.Connection") 

'Note HDR=Yes, that is, first row contains field names ' 
'and FMT delimted, ie CSV ' 

strCon="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\Docs\;" _ 
& "Extended Properties=""text;HDR=Yes;FMT=Delimited"";" 

cn.open strcon 

'You would not need delimiters ('') if last field is numeric: '  
strSQL="SELECT FieldName1, FieldName2 INTO New.csv FROM Old.csv " _ 
& " WHERE LastFieldName='SomeTextValue'" 

'Creates new csv file 
cn.Execute strSQL 
+0

मैंने पिछले –

+0

+1 में एक ही चीज़ को पूरा करने के लिए एक समान तकनीक का उपयोग किया है, यह इस तरह के बड़े डेटासेट के लिए सबसे अच्छा समाधान है, मैंने पिछले –

+0

@ फ़ियोनुआला में समेकित डेटा के साथ ऐसा किया है, मैं हूं स्मृति में एक CSV फ़ाइल पढ़ने के लिए अपने उत्तर का उपयोग कर। हालांकि, मुझे 280 चर सीमा का अनुभव हो रहा है जैसा कि मैंने एक प्रश्न में बताया है: http://stackoverflow.com/questions/34230062/excel-vba-reading-csv-file-with-large-multiline-values-using-adodb साथ-साथ-जेट-या-क्या आप इस तरह के व्यवहार का अनुभव करते थे और इस सीमा को दूर करने के बारे में कोई विचार था? – IzCe

4

यह सीधे आपके प्रश्न का उत्तर नहीं है, लेकिन grep (या Windows समकक्ष से एक) वास्तव में इस के लिए चमक होता है, जैसे,

grep -e <regex_filter> foo.csv > bar.csv 
+0

विंडोज़ प्रश्न के लिए यूनिक्स क्यों? – Fionnuala

+1

जीईपी के विंडोज वेरिएंट: विनग्रेप (http://www.wingrep.com/), पावरग्रेप (http://www.powergrep.com/), और विंडोज़ के लिए जीएनयू जीआरपी (http://gnuwin32.sourceforge.net/ संकुल/grep.htm)। –

+1

यह देखते हुए कि grep किसी रूप में उपलब्ध है, और इसका पूरा उद्देश्य रेगेक्स से मेल खाने वाली रेखाओं को प्रिंट करना है, जो कि प्रश्न में उल्लिखित फ़िल्टरिंग के लिए पर्याप्त लग रहा था, यह एक प्राकृतिक फिट की तरह लग रहा था। –

8

निम्नलिखित कोड को चाल चलनी चाहिए। मेरे पास एक्सेल मेरे सामने नहीं है, इसलिए मैंने इसका परीक्षण नहीं किया है, लेकिन अवधारणा ध्वनि है।

यदि यह बहुत धीमा हो जाता है, तो हम दक्षता में सुधार के तरीकों को देख सकते हैं।

Sub SelectSomeRecords() 
    Dim testLine As String 

    Open inputFileName For Input As #1 
    Open outputFileName For Output As #2 

    While Not EOF(1) 
     Line Input #1, testLine 
     If RecordIsInteresting(testLine) Then 
      Print #2, testLine 
     End If 
    Wend 

    Close #1 
    Close #2 
End Sub 

Function RecordIsInteresting(recordLine As String) As Boolean 
    Dim lineItems(1 to 8) As String 

    GetRecordItems(lineItems(), recordLine) 

    ''// do your custom checking here: 
    RecordIsInteresting = lineItems(8) = "LS1 7AA" 
End Function 

Sub GetRecordItems(items() As String, recordLine as String) 
    Dim finishString as Boolean 
    Dim itemString as String 
    Dim itemIndex as Integer 
    Dim charIndex as Long 
    Dim inQuote as Boolean 
    Dim testChar as String 

    inQuote = False 
    charIndex = 1 
    itemIndex = 1 
    itemString = "" 
    finishString = False 

    While charIndex <= Len(recordLine) 
     testChar = Mid$(recordLine, charIndex, 1) 

     finishString = False 

     If inQuote Then 
      If testChar = Chr$(34) Then 
       inQuote = False 
       finishString = True 
       charIndex = charIndex + 1 ''// ignore the next comma 
      Else 
       itemString = itemString + testChar 
      End If 
     Else 
      If testChar = Chr$(34) Then 
       inQuote = True 
      ElseIf testChar = "," Then 
       finishString = True 
      Else 
       itemString = itemString + testChar 
      End If 
     End If 

     If finishString Then 
      items(itemIndex) = itemString 
      itemString = "" 
      itemIndex = itemIndex + 1 
     End If 

     charIndex = charIndex + 1 
    Wend 
End Sub 
1

मैं (आप में "उपकरण ... संदर्भ" यह देखना चाहिए नियमित अभिव्यक्ति पुस्तकालय पर एक नज़र पूरे करने की सलाह चाहते हैं के रूप में "माइक्रोसॉफ्ट VBScript रेगुलर एक्सप्रेशन 5.5" या बहुत कुछ इसी तरह।

वहाँ

रेग एक्सप दोनों के नमूने हैं और इस स्थान पर एक काफी व्यापक चरित्र-दर-चरित्र हैं: http://www.xbeat.net/vbspeed/c_ParseCSV.php। ध्यान दें कि रेगेक्सपी संस्करण कम है!

मज़े करें ...

2

Excel में Input # बयान पर देखो मदद

नमूना उपयोग होगा:

Input #fnInput, s_Forename, s_Surname, dt_DOB, i_Something, s_Street, s_Town, s_County, s_Postcode 

और फिर Write # कथन का उपयोग मिलान रिकॉर्ड को लिखने के लिए फिर से

केवल समस्या हो सकती है कि आउटपुट में दिनांक प्रारूप # 1 9 67-07-01 # के रूप में समाप्त होगा लेकिन यह प्रारूप 01/07/1967 के विपरीत स्पष्ट नहीं है जो यूके में 1 जुलाई और यूएस में 7 जनवरी का प्रतिनिधित्व करेगा। आप तारीख के स्वरूपण को संरक्षित करने की जरूरत है तो यह एक स्ट्रिंग के रूप में बाहर लिखें:

s_DOB = Format(dt_DOB, "dd/mm/yyyy") 
2

कुछ भी आप एक्सेल में VBA के साथ एक पंक्ति-में-एक-समय कर सकते हैं, आप VBA के साथ पहुँच में कर सकते हैं ; प्लस बहुत अधिक क्योंकि यह एक स्प्रेडशीट के बजाय डेटाबेस है। क्या पहुंच आपके लिए अनुपलब्ध है?

लॉजिकल वर्कशीट्स, पंक्तियों और कॉलम की तुलना में लॉजिकल टेबल, रिकॉर्ड और फ़ील्ड से निपटना बहुत आसान है।

इनपुट के लिए, "डेटा/आयात बाहरी डेटा/टेक्स्ट/सीएसवी" क्यों काम नहीं करता है? क्या इनपुट वास्तव में पोर्टेबल सीएसवी नहीं है?

+0

एक्सेल में 1.2 मिलियन पंक्तियां काम नहीं करने जा रही हैं, हालांकि, जेट इंजन का उपयोग करके डेटा एडीओ के साथ छेड़छाड़ की जा सकती है, यानी इंजन जिस पर एक्सेस आधारित है। इसलिए मेरा जवाब। – Fionnuala

+1

ठीक है - तो पुष्टि करने के लिए - एक्सेस उपलब्ध नहीं है? वैसे भी, यदि आप एडीओ के साथ जेट तक पहुंच सकते हैं, तो आप Excel VBA के साथ Excel के भीतर से एक एक्सेस एमडीबी डेटाबेस भी खोल सकते हैं और वहां डेटा स्टोर कर सकते हैं - आपको ऐसा करने के लिए इंस्टॉल एक्सेस की भी आवश्यकता नहीं होगी। – dkretz

3

मैंने एक्सेल में वीबीए से मनमाने ढंग से सीएसवी फ़ाइल सफलतापूर्वक खोलने के लिए ऊपर दिए गए कोड के निम्नलिखित व्युत्पन्न का उपयोग किया।

विकल्प स्पष्ट
लोक cn कनेक्शन
सार्वजनिक उप छदाम()
मंद strcon स्ट्रिंग
मंद strsql स्ट्रिंग के रूप में के रूप में के रूप में
मंद रु अभिलेख सेट

सेट cn = CreateObject ("ADODB के रूप में कनेक्शन ")

स्ट्रोक =" प्रदाता = माइक्रोसॉफ्ट.जेट.ओएलडीबी.4.0; डेटा स्रोत = सी: \ बिन \ होमप्लानेट \; " _
& "विस्तारित गुण =" "पाठ; एचडीआर = हाँ; एफएमटी = सीमित" ";

cn.Open strcon

strsql =
सेट रु = नई ADODB.Recordset
rs.Open strsql यहाँ "astuname.csv से चुनें *", cn
DoEvents 'ठहराव है और गुण, निरीक्षण करने के लिए rs.Close
End Sub

रु (recordset) क्षेत्रों का संग्रह है, एक गणना संपत्ति के साथ। एक प्रकार की संपत्ति के रूप में प्रत्येक क्षेत्र।

आप अनुक्रम संख्या से क्षेत्रों को संदर्भित कर सकते ...

Debug.Print rs.Fields (rs.Fields.Count - 1) .Type

इस पर्याप्त है?

यदि नहीं, इनपुट फ़ाइल की पहली पंक्तियों को पोस्ट करें और मैं इसे बाकी तरीके से ले जाऊंगा।

संबंधित मुद्दे