1

複数の Salesforce カスタム オブジェクトに移動する必要があるフィールドを含む CSV があります。解析を処理する APEX クラスを作成しました。ただし、VisualForce ページからクラスを呼び出すと、次のメッセージが表示されます。

Collection size 3,511 exceeds maximum size of 1,000.

私の APEX クラスは次のとおりです (このトピックに関する 2 つのブログ投稿からまとめたものです)。

public class parseCSV{  
public Blob contentFile { get; set; }    
public String nameFile { get; set; }    
public Integer rowCount { get; set; }    
public Integer colCount { get; set; }    
public List<List<String>> getResults() {        
 List<List<String>> parsedCSV = new List<List<String>>();        
 rowCount = 0;        
 colCount = 0;        
 if (contentFile != null){            
 String fileString = contentFile.toString();            
 parsedCSV = parseCSV(fileString, false);            
 rowCount = parsedCSV.size();            
 for (List<String> row : parsedCSV){                
 if (row.size() > colCount){                    
 colCount = row.size();                
}            
}        
}        
return parsedCSV;    
}  
public static List<List<String>> parseCSV(String contents,Boolean skipHeaders) {        
List<List<String>> allFields = new List<List<String>>();    
// replace instances where a double quote begins a field containing a comma    
// in this case you get a double quote followed by a doubled double quote    
// do this for beginning and end of a field    
contents = contents.replaceAll(',"""',',"DBLQT').replaceall('""",','DBLQT",');    
// now replace all remaining double quotes - we do this so that we can reconstruct    
// fields with commas inside assuming they begin and end with a double quote    
contents = contents.replaceAll('""','DBLQT');    
// we are not attempting to handle fields with a newline inside of them    
// so, split on newline to get the spreadsheet rows    
List<String> lines = new List<String>();    
try {        
lines = contents.split('\n');    
} 
catch (System.ListException e) {        
System.debug('Limits exceeded?' + e.getMessage());    
}    
Integer num = 0;    
for(String line : lines) {        
// check for blank CSV lines (only commas)        
if (line.replaceAll(',','').trim().length() == 0) break;
List<String> fields = line.split(',');          
List<String> cleanFields = new List<String>();        
String compositeField;        
Boolean makeCompositeField = false;        
for(String field : fields) {            
if (field.startsWith('"') && field.endsWith('"')) 
{
            cleanFields.add(field.replaceAll('DBLQT','"'));            
} 
else if (field.startsWith('"')) {                
makeCompositeField = true;                
compositeField = field;            
}
else if (field.endsWith('"')) {
compositeField += ',' + field;                
cleanFields.add(compositeField.replaceAll('DBLQT','"'));                
makeCompositeField = false;            
}
else if (makeCompositeField) {                
compositeField +=  ',' + field;            
}
else {
cleanFields.add(field.replaceAll('DBLQT','"'));            
}        
}                
allFields.add(cleanFields);    
}    
if (skipHeaders) allFields.remove(0);    
return allFields;       
}  
}

上記のクラスが CSV から適切なカスタム オブジェクトに正しい列を挿入するようにするにはどうすればよいですか?

一部のオブジェクトには他のオブジェクトへのルックアップが含まれているため、データが最初にルックアップ フィールドにロードされ、次に子テーブルにロードされるようにするにはどうすればよいですか?

最後に、上記のエラー メッセージを回避するにはどうすればよいですか? VisualForce ページの使用以外に提案されていることはありますか?

あなたの助けと指導に感謝します。

4

4 に答える 4

5

興味深いことに、これが visualforce ページからのものであるという要件はありますか? Data Loader を使用して CSV をロードしたり、bulk API を使用して自分でソリューションを構築したりすることもできます。

ページからそれを行う必要がある場合は、すぐに新しい行に分割するのではなく、 and を使用substringしてindexOf、入力文字列から一度に 1 行だけ取​​り出し、処理しながら処理することをお勧めします。

于 2012-05-03T06:30:01.997 に答える
1

このセールスフォースの例では、一重引用符が単独で使用されている場合は処理されません。

例えば、

",",XXX,YYY

これは、フィールドが 3 つしかない場合に 4 つのフィールドを返します。

問題は次の場所にあります。

if (field.startsWith('"') && field.endsWith('"')) 

次のようなフィールドがある場合:

"

二重引用符で始まり、終わりますが、それはテストの意図ではありません

次のように変更します。

if (field.length() > 1 && field.startsWith('"') && field.endsWith('"')) {

そしてそれはうまくいくでしょう。

完全に修正された例は次のとおりです。

    public class parseCSV{  
public Blob contentFile { get; set; }    
public String nameFile { get; set; }    
public Integer rowCount { get; set; }    
public Integer colCount { get; set; }    
public List<List<String>> getResults() {        
 List<List<String>> parsedCSV = new List<List<String>>();        
 rowCount = 0;        
 colCount = 0;        
 if (contentFile != null){            
 String fileString = contentFile.toString();            
 parsedCSV = parseCSV(fileString, false);            
 rowCount = parsedCSV.size();            
 for (List<String> row : parsedCSV){                
 if (row.size() > colCount){                    
 colCount = row.size();                
}            
}        
}        
return parsedCSV;    
}  
public static List<List<String>> parseCSV(String contents,Boolean skipHeaders) {        
List<List<String>> allFields = new List<List<String>>();    
// replace instances where a double quote begins a field containing a comma    
// in this case you get a double quote followed by a doubled double quote    
// do this for beginning and end of a field    
contents = contents.replaceAll(',"""',',"DBLQT').replaceall('""",','DBLQT",');    
// now replace all remaining double quotes - we do this so that we can reconstruct    
// fields with commas inside assuming they begin and end with a double quote    
contents = contents.replaceAll('""','DBLQT');    
// we are not attempting to handle fields with a newline inside of them    
// so, split on newline to get the spreadsheet rows    
List<String> lines = new List<String>();    
try {        
lines = contents.split('\n');    
} 
catch (System.ListException e) {        
System.debug('Limits exceeded?' + e.getMessage());    
}    
Integer num = 0;    
for(String line : lines) {        
// check for blank CSV lines (only commas)        
if (line.replaceAll(',','').trim().length() == 0) break;
List<String> fields = line.split(',');          
List<String> cleanFields = new List<String>();        
String compositeField;        
Boolean makeCompositeField = false;        
for(String field : fields) {            
if (field.length() > 1 && field.startsWith('"') && field.endsWith('"')) {
{
            cleanFields.add(field.replaceAll('DBLQT','"'));            
} 
else if (field.startsWith('"')) {                
makeCompositeField = true;                
compositeField = field;            
}
else if (field.endsWith('"')) {
compositeField += ',' + field;                
cleanFields.add(compositeField.replaceAll('DBLQT','"'));                
makeCompositeField = false;            
}
else if (makeCompositeField) {                
compositeField +=  ',' + field;            
}
else {
cleanFields.add(field.replaceAll('DBLQT','"'));            
}        
}                
allFields.add(cleanFields);    
}    
if (skipHeaders) allFields.remove(0);    
return allFields;       
}  
}
于 2012-10-26T22:11:32.967 に答える
1

4MB の CSV ファイルを処理しようとしたところ、SalesForce から「Regext too complex」というエラーが返されました。問題はあなたのものに似ていると思います。

バッチ頂点とイテレータを使用して修正しました。詳細はこちらのリンク

于 2012-09-26T14:49:32.967 に答える
1

変換された CSV データ (1000 レコード以上) をリストに保存して Visualforce ページに表示しようとしたときにも、そのメッセージを受け取りました。インポートされたレコードを表示する場合 (これは便利な機能です)、表示するリストの要素が 1000 未満であることを確認する必要があります。

レコードを Salesforce オブジェクトに挿入するには、次のようにします。

「parseCSV」という静的メソッドを使用して「Util」というクラスを定義しました (以下を参照)。

public blob importedCSV {get;set;}

list<list<string>> parsedCSV = Util.parseCSV(importedCSV.toString(),true);
list<Custom_Object__c> cObjsToInsert = new list<Custom_Object__c>();
for(list<string> line:parsedCSV){
    Custom_Object__c c = new Custom_Object__c();
    c.Name=line[0];
    c.String_Field__c=line[2];
    c.Currency_Field__c=decimal.valueof(line[3]);
    if(line.size()>4)
        c.Description__c=line[4];
    cObjsToInsert.add(c);
}
insert cObjsToInsert;

通常、CSV を処理してデータを Salesforce オブジェクトに挿入するとき、サイズ エラーは発生しません。CSV をインポートし、CSV を何らかの方法で処理し、処理されたデータを CSV、Excel、またはテキスト (固定幅) 形式にエクスポートする Visualforce ページを作成しました。CSV を Visualforce ページに読み込み、データを添付ファイルとしてダミー レコードに保存します。次に、添付ファイルを取得し、データを処理して、目的の形式に出力する別の Visualforce ページにユーザーを誘導します。

このコードをどこで入手したか思い出せませんが、魅力的に機能します。parseCSVメソッドのテスト コードも書きました。

public static list<list<String>> parseCSV(String contents,Boolean skipHeaders) {
    list<list<String>> allFields = new List<List<String>>();

    // replace instances where a double quote begins a field containing a comma
    // in this case you get a double quote followed by a doubled double quote
    // do this for beginning and end of a field
    contents = contents.replaceAll(',"""',',"DBLQT').replaceall('""",','DBLQT",');
    // now replace all remaining double quotes - we do this so that we can reconstruct
    // fields with commas inside assuming they begin and end with a double quote
    contents = contents.replaceAll('""','DBLQT');
    // we are not attempting to handle fields with a newline inside of them
    // so, split on newline to get the spreadsheet rows
    list<String> lines=new list<string>();
    try {
        lines = contents.split('\n');
    } catch (System.ListException e) {
        System.debug('Limits exceeded?  '+e.getMessage());
    }
    integer num=0;
    for(string line :lines) {
        // check for blank CSV lines (only commas)
        if(line.replaceAll(',','').trim().length()==0) 
            break;
        list<String> fields=line.split(',');    
        list<String> cleanFields=new list<String>();
        string compositeField;
        boolean makeCompositeField=false;
        for(string field : fields) {
            if(field.startsWith('"') && field.endsWith('"')) {
                cleanFields.add(field.replaceAll('DBLQT','"').removeStart('"').removeEnd('"'));
            } else if(field.startsWith('"')) {
                makeCompositeField = true;
                compositeField = field;
            } else if(field.endsWith('"')) {
                compositeField += ',' + field;
                cleanFields.add(compositeField.replaceAll('DBLQT','"').removeStart('"').removeEnd('"'));
                makeCompositeField = false;
            } else if(makeCompositeField) {
                compositeField +=  ',' + field;
            } else{
                cleanFields.add(field.replaceAll('DBLQT','"').removeStart('"').removeEnd('"'));
            }
        }  
        allFields.add(cleanFields);
    }
    if(skipHeaders) 
        allFields.remove(0);
    return allFields;       
}//END ParseCSV

@isTest
private static void testParseCSV(){
    string contents='Field1,Field2,Field3\n1,,Smith\n2,Fred,O\'Connor\n3,Destiny,"Awaits, DDS"\n\n';
    list<list<string>> parsedCSV=Util.parseCSV(contents,true);
    //line 1
    system.assertEquals('1',parsedCSV[0][0]);
    system.assertEquals('',parsedCSV[0][1]);
    system.assertEquals('Smith',parsedCSV[0][2]);
    //line 2
    system.assertEquals('2',parsedCSV[1][0]);
    system.assertEquals('Fred',parsedCSV[1][1]);
    system.assertEquals('O\'Connor',parsedCSV[1][2]);
    //line 3
    system.assertEquals('3',parsedCSV[2][0]);
    system.assertEquals('Destiny',parsedCSV[2][1]);
    system.assertEquals('Awaits, DDS',parsedCSV[2][2]);
}//END

このコードを「Util」というクラスに配置しました。BLOB がある場合は、まずそれを文字列に変換し、メソッドを呼び出します。例えば

blob b=inputBlob;
list<list<string>> parsedCSV = Util.parseCSV(b.toString(),true);
于 2013-06-06T02:01:47.653 に答える