एक्सेस 2010 के बाद से, एक्सेस ने अटैचमेंट डेटा प्रकार का समर्थन किया है जो सतह पर छोटी छवियों या फ़ाइलों को संग्रहीत करने के लिए एक सुविधाजनक सुविधा की तरह लगता है। हालांकि, एक त्वरित Google खोज आमतौर पर दिखाएगा कि उन्हें सबसे अच्छा टाला जाता है। यह सब इस तथ्य पर उबलता है कि अनुलग्नक डेटा प्रकार वास्तव में एक बहु-मूल्यवान फ़ील्ड (एमवीएफ) है, और ये कई समस्याओं के साथ आते हैं। एक के लिए, आप एक बार में कई रिकॉर्ड डालने या अपडेट करने के लिए क्वेरी का उपयोग करने में असमर्थ होंगे। वास्तव में, इस तरह के डेटा प्रकार वाली कोई भी तालिका आपको बहुत सारे कोड करने के लिए मजबूर करती है और केवल इसी कारण से, हम सामान्य रूप से ऐसे डेटा प्रकारों का उपयोग करने से बचते हैं।
हालाँकि, एक समस्या है। हम छवि गैलरी और थीम का उपयोग करना पसंद करते हैं, जो दोनों एक सिस्टम टेबल पर निर्भर करते हैं, MSysResources
जो दुर्भाग्य से अनुलग्नक डेटा प्रकारों का उपयोग करता है। इसने हमारे मानक पुस्तकालय में संसाधनों के प्रबंधन के लिए एक समस्या पैदा कर दी है क्योंकि हम MSysResources
का उपयोग करना चाहते हैं। लेकिन हम उन्हें आसानी से अपडेट या थोक में सम्मिलित नहीं कर सकते।
अनुलग्नक डेटा प्रकार (साथ ही एमवीएफ) आपको एमवीएफ फ़ील्ड से निपटने के दौरान "पंक्ति-दर-एगोनाइजिंग-पंक्ति" प्रोग्रामिंग का उपयोग करने के लिए मजबूर करता है, यह अटैचमेंट फ़ील्ड के साथ एक ट्वोफर है क्योंकि आपको LoadFromFileकोड का उपयोग करना होगा। कोड> या
SaveToFile
तरीके। Microsoft के पास उन विधियों के उदाहरणों के साथ एक लेख है। इस प्रकार, आपको नए रिकॉर्ड जोड़ते समय फाइल सिस्टम के साथ बातचीत करनी चाहिए। सभी स्थितियों में हमेशा वांछनीय नहीं होता है। अब, अगर हम एक टेबल से दूसरी टेबल पर कॉपी कर रहे हैं, तो हम कुछ ऐसा करके फाइल सिस्टम पर बाउंस होने से बच सकते हैं:
Dim SourceParentRs As DAO.Recordset2 Dim SourceChildRs As DAO.Recordset2 Dim TargetParentRs As DAO.Recordset2 Dim TargetChildRs As DAO.Recordset2 Dim SourceField As DAO.Field2 Set SourceParentRs = db.OpenRecordset("TableWithAttachmentField", dbOpenDynaset) Set TargetParentRs = db.OpenRecordset("AnotherTableWithAttachmentField", dbOpenDynaset, dbAppendOnly) Do Until SourceParentRs.EOF TargetParentRs.AddNew For Each SourceField In SourceParentRs.Fields If SourceField.Type <> dbAttachment Then TargetParentRs.Fields(SourceField.Name).Value = SourceField.Value End If Next TargetParentRs.Update 'Must save record first before can edit MVF fields TargetParentRs.Bookmark = TargetParentRs.LastModified Set SourceChildRs = SourceParentRs.Fields("Data").Value Set TargetChildRs = TargetParentRs.Fields("Data").Value Do Until SourcechildRs.EOF TargetChildRs.AddNew Const ChunkSize As Long = 32768 Dim TotalSize As Long Dim Offset As Long TotalSize = SourceChildRs.Fields("FileData").FieldSize Offset = TotalSize Mod ChunkSize TargetChildRs.Fields("FileData").AppendChunk(SourceChildRs.GetChunk(0, Offset) Do Until Offset > TotalSize TargetChildRs.Fields("FileData").AppendChunk(SourceChildRs.GetChunk(Offset, ChunkSize) Offset = Offset + ChunkSize Loop TargetChildRs.Update SourceChildRs.MoveNext Loop TargetParentRs.Update SourceParentRs.MoveNext Loop
पवित्र लूपिंग, बैटमैन! यह बहुत सारा कोड है, बस एक टेबल से दूसरी टेबल में अटैचमेंट कॉपी करने के लिए। भले ही हम फाइल सिस्टम पर बाउंस नहीं करते हैं, यह भी बहुत धीमा है। हमारे अनुभव में, एक एकल अनुलग्नक वाले 1000 रिकॉर्ड वाली तालिका में मिनट लग सकते हैं बस संसाधित करने के लिए। अब, जब आप आकार पर विचार करते हैं तो यह काफी बड़ा हो जाता है। संलग्नक वाली तालिका उतनी बड़ी नहीं है। वास्तव में, आइए एक प्रयोग करते हैं। आइए देखें कि अगर मैं डेटाशीट के माध्यम से कॉपी और पेस्ट करता हूं तो क्या होता है:
इसलिए कॉपी करना और चिपकाना व्यावहारिक रूप से तात्कालिक है। जाहिर है कि चिपकाने के लिए इस्तेमाल किया जाने वाला कोड वही कोड नहीं है जिसे हम वीबीए में इस्तेमाल करेंगे। हालाँकि, हम बड़े आस्तिक हैं कि यदि हम इसे अंतःक्रियात्मक रूप से कर सकते हैं, तो हम इसे VBA में भी कर सकते हैं। क्या हम वीबीए में इंटरेक्टिव पेस्टिंग की गति को दोहरा सकते हैं? इसका उत्तर हां में मिलता है, हम कर सकते हैं!
के साथ गति करें…. एक्सएमएल?
हैरानी की बात है कि संलग्नक सहित डेटा कॉपी करने का सबसे तेज़ तरीका प्रदान करने वाली विधि XML फ़ाइलों के माध्यम से है। मैं स्वीकार करूंगा कि मैं सीमाओं के लिए समाधान के अलावा एक्सएमएल फाइलों तक नहीं पहुंचता हूं। औसतन, XML फ़ाइलें अन्य फ़ाइल स्वरूपों की तुलना में अपेक्षाकृत धीमी होती हैं लेकिन इस मामले में, XML का एक बड़ा लाभ होता है; इसमें एमवीएफ का वर्णन करने में कोई समस्या नहीं है। आइए एक XML फ़ाइल बनाएँ और एक XML फ़ाइल के आयात/निर्यात से हमें मिलने वाली क्षमताओं की जाँच करें।
XML फ़ाइल को सहेजने के लिए पथ सेट करने के लिए सामान्य निर्यात विज़ार्ड संवाद के बाद, हमें इस तरह का एक संवाद मिलेगा:
यदि हम "More Option..." बटन पर क्लिक करते हैं, तो हमें इसके बजाय यह डायलॉग मिलता है:
इस संवाद से, हम कुछ और सुराग देखते हैं कि क्या संभव है; अर्थात्:
- हमारे पास फ़िल्टर लागू करके पूरी तालिका या तालिका के केवल एक सबसेट को निर्यात करने का विकल्प है
- हम एक्सएमएल आउटपुट को बदल सकते हैं।
- हम तालिका की सामग्री के अलावा स्कीमा का वर्णन कर सकते हैं।
मुझे लगता है कि स्कीमा को एम्बेड करना सबसे अच्छा है; डिफ़ॉल्ट इसे निर्यात करना है लेकिन एक अलग फ़ाइल के रूप में। हालाँकि, यह त्रुटि-प्रवण हो सकता है और वे XSD फ़ाइल को XML फ़ाइल के साथ शामिल करना भूल सकते हैं। इसे दिखाए गए स्कीमा टैब के माध्यम से बदला जा सकता है:
आइए इसे निर्यात करना समाप्त करें और परिणामी XML फ़ाइल के डेटा पर एक त्वरित नज़र डालें।
ध्यान दें कि अटैचमेंट डेटा
. में वर्णित हैं सबट्री और फ़ाइल सामग्री बेस -64 एन्कोडेड है। आइए XML फ़ाइल आयात करने का प्रयास करें। इंपोर्ट विजार्ड के माध्यम से जाने के बाद, हमें यह डायलॉग मिलेगा:
निम्नलिखित विशेषताओं पर ध्यान दें:
- निर्यात की तरह, हमारे पास XML को रूपांतरित करने का विकल्प है।
- हम नियंत्रित कर सकते हैं कि संरचना, डेटा या दोनों आयात करना है या नहीं
यदि हम XML फ़ाइल को आयात करना समाप्त कर देते हैं, तो हम पाते हैं कि यह कॉपी-पेस्ट ऑपरेशन जितना तेज़ है, उतना ही तेज़ है।
अब हम जानते हैं कि अटैचमेंट के साथ कई रिकॉर्ड कॉपी करने का एक बेहतर तरीका है। लेकिन इस स्थिति में, हम इसे अंतःक्रियात्मक रूप से करने के बजाय प्रोग्रामेटिक रूप से करना चाहते हैं। क्या हम वही कर सकते हैं जो हमने अभी किया था? फिर इसका जवाब हां में है। एक ही काम करने के कई तरीके हैं लेकिन मुझे लगता है कि सबसे आसान तरीका 3 नए तरीकों का उपयोग करना है जो एप्लिकेशन
में जोड़े गए थे। एक्सेस 2010 के बाद से ऑब्जेक्ट:
ExportXML
विधिTransformXML
विधिImportXML
विधि
ध्यान दें कि ExportXML
विधि विभिन्न वस्तुओं से निर्यात का समर्थन करती है। हालाँकि, क्योंकि यहाँ उद्देश्य अनुलग्नक फ़ील्ड के साथ तालिका के रिकॉर्ड को कॉपी या अपडेट करने में सक्षम होना है, हमारे लिए उपयोग करने के लिए सबसे अच्छा ऑब्जेक्ट प्रकार एक सहेजी गई क्वेरी है। एक सहेजी गई क्वेरी के साथ, हम नियंत्रित कर सकते हैं कि कौन सी पंक्तियां डाली जानी चाहिए या अपडेट की जानी चाहिए और हम आउटपुट को आकार भी दे सकते हैं। यदि आप MSysResources
. के स्कीमा डिज़ाइन को देखें तो नीचे दी गई तालिका:
एक संभावित समस्या है। जब भी हम थीम या इमेज का उपयोग करते हैं, तो हम आइटम को नाम से संदर्भित करते हैं, आईडी से नहीं। हालांकि, नाम
कॉलम अद्वितीय नहीं है और तालिका की प्राथमिक कुंजी नहीं है। इसलिए, जब हम रिकॉर्ड जोड़ते या अपडेट करते हैं, तो हम Name
. से मिलान करना चाहते हैं कॉलम, न कि Id
कॉलम। इसका मतलब है कि जब हम निर्यात करते हैं, तो हमें संभवत:Id
. शामिल नहीं करना चाहिए कॉलम और हमें केवल Name
. की अनूठी सूची निर्यात करनी चाहिए यह सुनिश्चित करने के लिए कि संसाधन अचानक "Open.png" से "Close.png" या कुछ मूर्खतापूर्ण न हो जाएं।
फिर हम उन रिकॉर्ड्स के स्रोत के रूप में कार्य करने के लिए एक क्वेरी बनाएंगे, जिन्हें हम MSysResources
में आयात करना चाहते हैं। टेबल। आइए इस SQL के साथ केवल रिकॉर्ड्स के सबसेट को फ़िल्टरिंग प्रदर्शित करने के लिए शुरू करें:
SELECT e.Data, e.Extension, e.Name, e.Type FROM Example AS e WHERE e.Name In ("blue","red","green");
फिर हम इसे qryResourcesExport
. के रूप में सहेजेंगे . फिर हम XML को एक्सपोर्ट करने के लिए VBA कोड लिख सकते हैं:
Application.ExportXML _ ObjectType:=acExportQuery, _ DataSource:="qryResourcesExport", _ DataTarget:="C:\Path\to\Resources.xml", _ OtherFlags:=acEmbedSchema
यह उस निर्यात का अनुकरण करता है जिसे हमने मूल रूप से अंतःक्रियात्मक रूप से किया था।
हालांकि, अगर हम परिणामी एक्सएमएल आयात करते हैं, तो हमारे पास मौजूदा तालिका में डेटा जोड़ने का विकल्प होता है। हम यह नियंत्रित नहीं कर सकते कि यह किस तालिका में संलग्न होगा; इसे एक ही नाम से एक टेबल या क्वेरी टेबल मिलेगी (उदा. qryResourcesExport
और उस क्वेरी में रिकॉर्ड संलग्न करें। यदि क्वेरी अद्यतन करने योग्य है, तो कोई समस्या नहीं है और यह उदाहरण
में सम्मिलित हो जाएगी जिस पर क्वेरी आधारित है। लेकिन क्या होगा यदि हमारे द्वारा उपयोग की जाने वाली स्रोत क्वेरी गैर-अद्यतन योग्य है या मौजूद नहीं हो सकती है? किसी भी स्थिति में, हम XML फ़ाइल को यथावत आयात करने में असमर्थ होंगे। यह या तो आयात करने में विफल हो सकता है या qryResourcesExport
. नामक एक नई तालिका बना सकता है जो हमारी मदद नहीं करता। और उदाहरण
. से डेटा कॉपी करने के मामले के बारे में क्या करने के लिए MSysResources
? हम उदाहरण
. में डेटा नहीं जोड़ना चाहते हैं टेबल।
वहीं TransformXML
बचाव का तरीका आता है। एक्सएमएल ट्रांसफॉर्मेशन कैसे लिखना है, इस बारे में एक पूरी चर्चा दायरे से बाहर है लेकिन आपको ट्रांसफॉर्मेशन का वर्णन करने के लिए एक्सएसएलटी स्टाइलशीट लिखने के तरीके पर पर्याप्त संसाधन खोजने में सक्षम होना चाहिए। ऐसे कई ऑनलाइन टूल हैं जिनका उपयोग आप अपने XSLT को मान्य करने के लिए भी कर सकते हैं। यहां एक है। साधारण मामले के लिए जहां हम केवल यह नियंत्रित करना चाहते हैं कि XML फ़ाइल को किस तालिका में रिकॉर्ड जोड़ना चाहिए, आप इस XSLT फ़ाइल के साथ आरंभ कर सकते हैं। फिर आप निम्न VBA कोड चला सकते हैं:
Application.TransformXML _ DataSource:="C:\Path\to\Resources.xml", _ TransformSource:="C:\Path\to\ResourcesTransform.xslt", _ OutputTarget:="C:\Path\to\Resources.xml", _ WellFormedXMLOutput:=True, _ ScriptOption:=acEnableScript
हम मूल XML फ़ाइल को रूपांतरित XML फ़ाइल से बदल सकते हैं, जो अब MSysResources
में सम्मिलित होगी तालिका के बजाय (संभवतः गैर-मौजूद क्वेरी/तालिका) qryResourcesExport
।
फिर हमें अपडेट को संभालने की जरूरत है। क्योंकि हम वास्तव में नए रिकॉर्ड जोड़ रहे हैं, और MSysResources
तालिका में डुप्लिकेट नामों पर कोई बाधा नहीं है, हमें यह सुनिश्चित करने की आवश्यकता है कि समान नाम वाले किसी भी मौजूदा रिकॉर्ड को पहले हटा दिया जाए। इसे इस तरह से एक समान क्वेरी लिखकर पूरा किया जा सकता है:
DELETE FROM MSysResources AS r WHERE r.Name In ("blue","red","green");
फिर VBA कोड चलाने से पहले इसे पहले चलाएँ:
Application.ImportXML DataSource:="C:\Path\to\Resources.xml", ImportOptions:=acAppendData
क्योंकि XML फ़ाइल रूपांतरित हो गई थी, ImportXML
विधि अब डेटा को MSysResources
. में सम्मिलित करेगी मूल क्वेरी के बजाय तालिका जिसका उपयोग हमने ExportXML
. के साथ किया था तरीका। हम निर्दिष्ट करते हैं कि इसे मौजूदा तालिका में डेटा जोड़ना चाहिए। हालाँकि, यदि तालिका मौजूद नहीं है, तो इसे बनाया जाएगा।
और इसके साथ, हमने अटैचमेंट फ़ील्ड के साथ तालिका का एक बड़ा अपडेट / इंसर्ट हासिल किया है जो मूल रिकॉर्डसेट-एंड-चाइल्ड-रिकॉर्डसेट VBA कोड की तुलना में बहुत तेज़ है। उम्मीद है की वो मदद करदे! साथ ही, यदि आपको एक्सेस एप्लिकेशन विकसित करने में सहायता चाहिए, तो बेझिझक हमसे संपर्क करें!