SSIS - приведение телефонов в порядок #2
В предыдущем посте на эту тему я написал о том, как "кривые" телефоны привести к формату. При этом, если одна строка на входе (в соответствующем поле) содержала список телефонов через запятую, то и на выходе ей соответствовала одна строка со списком телефонов в поле, так же через запятую. Исправлялся только формат.
Разберем более сложный случай - из каждой строки на входе нужно получить на выходе столько строк, сколько там есть телефонов. Например, на входе строка со значением в поле "8 963 1112233, 556 5554; 667 67 67", на выходе должна дать три строки: "+7(963)111-22-33", "+7(495)556-55-54" и "+7(495)667-67-67". Разделитель может быть как запятая, так и точка с запятой.
Для этого вставляем в поток Script Component, где создаем Output для которого свойство SyncronousInputID выставляем в None:

Код пишем по такому образцу:
...
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.Text;
...
public override void Input0_ProcessInputRow(Input0Buffer Row)
{
if (!Row.PhonesIn_IsNull)
{
if (!Row.PhonesIn_IsNull)
{
var countryPref = "7"; // we assume, that all phones are domestic and harcode country code
var defaultCityPref = "495"; // default city or operator prefix
var phones = Row.PhonesIn.Replace(';', ',').Split(','); // phones in string should be separated with commas or semicolons
var e = phones.GetEnumerator();
while (e.MoveNext())
{
var phone = e.Current.ToString().Trim();
var r1 = new Regex(@"(.*)(\d).*(\d).*(\d).*(\d).*(\d).*(\d).*(\d)\D*$", RegexOptions.IgnoreCase); // expression to match phone number
var r2 = new Regex(@".*(\d{3})\D*$", RegexOptions.IgnoreCase); // expression to match city or operator prefix
var m = r1.Match(phone);
if (m.Success)
{
var pref = r2.Match(m.Groups[1].Value).Groups[1].ToString(); // get prefix out
pref = (pref.Equals("095")) ? "495" : pref; // replace old Moscow prefix with new
if (pref.Length == 0) pref = defaultCityPref;
Output0Buffer.AddRow();
Output0Buffer.Phone=
(
"+" + countryPref + // phones prefixed with '+' and country code
"(" + pref + ")" + // city or operator prefix taken in curves
m.Groups[2].Value +
m.Groups[3].Value +
m.Groups[4].Value + "-" +
m.Groups[5].Value +
m.Groups[6].Value + "-" +
m.Groups[7].Value +
m.Groups[8].Value);
}
}
}
}
}
Для более подробной информации можно почитать "Creating an Asynchronous Transformation with the Script Component".
О чем ещё следует упомянуть - асинхронные компоненты "вбирают" все данные потока перед тем как их выпустить (а не порциями) - это может быть важно, если у вас много данных.