SalesNow CSV 自動取込
:LiTarget: 用途
SalesNow CSV を判定してメタ行スキップ・ヘッダ自動マッピング・重複検知3軸(社名/URL/電話)でリッチ取込。
:LiSparkle: 特徴
- SalesNow CSV 自動判定
- メタ行(先頭数行)スキップ
- ヘッダ自動マッピング
- 重複検知3軸(社名/URL/電話)
- リッチデータ生成
- Slack 通知
:LiCode: コード(コピペ用)
// SalesNow CSV 自動判定 + 取込(簡略版)
function parseSalesNowCSV(csvText) {
const lines = csvText.split(/\r?\n/);
// 1. SalesNow 判定: 先頭数行に「SalesNow」or 特定メタが含まれる
const isSalesNow = lines.slice(0, 5).some(l => /SalesNow|検索条件|抽出日時/.test(l));
// 2. メタ行スキップ(先頭の '#' or 空行 or 検索条件などを除外)
let headerIdx = lines.findIndex(l => /会社名|社名|URL|電話/.test(l));
if (headerIdx < 0) throw new Error('ヘッダ行が見つかりません');
const headers = lines[headerIdx].split(',').map(h => h.trim());
const rows = lines.slice(headerIdx + 1).filter(l => l.trim());
// 3. ヘッダ自動マッピング
const FIELD_MAP = {
'会社名': 'company', '社名': 'company',
'ホームページURL': 'url', 'URL': 'url',
'代表電話番号': 'tel', '電話': 'tel',
'住所': 'address', '業種': 'industry',
'salesNowリンク': 'salesNowLink',
};
const fieldIndex = {};
headers.forEach((h, i) => { if (FIELD_MAP[h]) fieldIndex[FIELD_MAP[h]] = i; });
return rows.map(row => {
const cols = row.split(',');
const out = {};
Object.entries(fieldIndex).forEach(([k, i]) => { out[k] = (cols[i] || '').trim(); });
return out;
});
}
// 重複検知3軸
function isDuplicate(newItem, existingList) {
return existingList.some(it =>
(newItem.company && it.company === newItem.company) ||
(newItem.url && it.url === newItem.url) ||
(newItem.tel && it.tel === newItem.tel)
);
}
:LiHandPointer: 使い方
対象プロジェクトに該当ファイルをコピーして、props を流し込むだけ。
:LiAlertCircle: 注意事項
- 依存パッケージを忘れず追加