C# 预测Excel将如何使用Postgres函数解释字符串

C# 预测Excel将如何使用Postgres函数解释字符串,c#,excel,perl,postgresql,C#,Excel,Perl,Postgresql,在我的工作场所中,我们有零件号项目编号,当输入Excel时,这些编号通常会转换为Excel认为用户的意思 例如,Excel进行以下更改: 00001234 => 1234 005678.0 => 5678 1234.560 => 1234.56 由于电子表格来自我们无法控制的来源,我们无法尝试控制Excel本身的行为 我有一个用VSTO C固定在Excel上的实用程序,它会转到Postgres表,尝试查找Excel零件号并将其转换回真实的零件号。简而言

在我的工作场所中,我们有零件号项目编号,当输入Excel时,这些编号通常会转换为Excel认为用户的意思

例如,Excel进行以下更改:

00001234   =>   1234
005678.0   =>   5678
1234.560   =>   1234.56
由于电子表格来自我们无法控制的来源,我们无法尝试控制Excel本身的行为

我有一个用VSTO C固定在Excel上的实用程序,它会转到Postgres表,尝试查找Excel零件号并将其转换回真实的零件号。简而言之,它看起来是这样的:

create table mdm.excel_lookup (
    actual_part_number text not null,
    excel_part_number text not null,
    lookup_priority integer not null,
    constraint excel_lookup_pk primary key (actual_part_number)
);
为了填充这个表,我使用plperl编写了一个函数,该函数试图获取任何给定的字符串,并预测Excel将如何将其搞乱。我相信我已经处理过带前导零和尾随零的数字,它们在小数点后被截断

不幸的是,这并不能涵盖一切。我不认为日期是可以预测的,所以我甚至可能不会尝试,除非有人有一个好主意。但是科学记数法呢?还有其他我没有想到的情况吗

我们的零件目录有150多万个零件,因此可能发生的情况有很多种可能性。如果我能抓住一个公平的百分比,我会很高兴

这是我迄今为止的职能。如果有人对我可以做些什么来捕获Excel可能做的其他事情有想法,我欢迎反馈。注意,到目前为止,这只处理我上面列出的场景

CREATE OR REPLACE FUNCTION excel_part(part_number text)
  RETURNS text AS
$BODY$

  my ($input) = @_;
  if ($input =~ /[A-Za-z]/) {
    return $input;
  } elsif ($input =~ /^0+(\d+)$/) {
    return $1;
  } elsif ($input =~ /^(\d+\.\d*)0+$/) {
    return $1 + 0;
  } else {
    return $input;
  }  

$BODY$
  LANGUAGE plperl VOLATILE
  COST 100;

另外,我没有和plperl结婚。我之所以使用它,是因为我知道Perl非常擅长文本处理。

我的建议是将所有零件号提取到excel中,在完成编号后保存文件,然后将结果作为新表或原始表中的列上载回数据库。这样你就不必担心你没有处理的任何案件。如果您经常基于此进行查找,它还允许您对列进行索引,并且可以轻松地检测出任何零件号,这些零件号在经过筛选后最终会变成重复的零件号

在excel重新上传之前,您必须有一些方法来确定它们是什么。如果有一个代理Id列,你可以使用它,否则做一些简单的事情,比如在零件号前面加上零件号,这样excel就会看到一个字符串,而不会碰它


如果simbabque是正确的,并且不同的excel版本可以做不同的事情,您可以通过多个不同版本的excel运行此过程并保存唯一的munges。

作为对Tim Tom回答的回应,这是一个C程序,它实现了他的建议。。。我觉得它很管用

    NpgsqlConnection conn = new NpgsqlConnection();
    conn.Open();

    Excel.Application xl = new Excel.Application();
    xl.Visible = true;
    Excel.Workbook wb = xl.Workbooks.Add(1);
    Excel.Worksheet ws = (Excel.Worksheet)wb.Sheets[1];

    List<string> parts = new List<string>();

    NpgsqlCommand cmd = new NpgsqlCommand("select prod_id from mdm.global_item_master",
        conn);
    NpgsqlDataReader reader = cmd.ExecuteReader();

    while (reader.Read())
        parts.Add(reader.GetString(0));

    reader.Close();

    NpgsqlCopyIn copy = new NpgsqlCopyIn(
        "copy mdm.excel_item_id from STDIN WITH NULL AS '' CSV;", conn);
    copy.Start();

    NpgsqlCopySerializer cs = new NpgsqlCopySerializer(conn);
    cs.Delimiter = ",";

    foreach (string part in parts)
    {
        ws.Cells[1, 1].Value2 = part;

        cs.AddString(part);
        cs.AddString(ws.Cells[1, 1].Text);
        cs.EndRow();
    }

    cs.Close();
    copy.End();

    conn.Close();

这些文件是CSV文件还是XLS文件?@simbabque-这是个好问题。它们以Excel本机文件的形式出现。我知道Excel也会发出非常好的CSV文件,但在这种情况下,在我们得到它之前就已经发出了声音。如果您可以为它们提供预设值,您可以修复单元格格式并锁定某些内容。这可能会有帮助。另外请注意,不同的本地版本的Excel会以不同的方式中断内容。主要问题是我们无法控制源代码。数据来自任何数量的来源,包括外部供应商和自动化作业。我们尽可能多地控制,但仍有电子表格是第二手、第三手、第四手的,我们无法追溯到原始版本。您必须将Excel和PostgreSQL表示转换为通用形式。e、 g.对于数字:将Excel和PostgreSQL中的零件号转换为固定精度的小数,并进行比较。你的函数必须处理科学记数法等。你将遇到的最大问题是一些白痴使用二进制浮点,所以你得到的是142.00199999部分,而不是142.002或其他任何部分。您需要某种形式的舍入,但如果您的零件号没有固定的小数位数限制,则这将很难实现。或者,如果他们可以有多个周期,我指的是不同的语言/国家版本,而不是版本。这是因为在不同的国家,用户输入的日期不同,小数点和逗号的处理也不同。那些有着独特魅力的东西。like 12.12将在德语Excel中转换为日期,尤其是导出到CSV时,将看起来像12。迪兹之类的。另一方面,在美国Excel中最有可能被视为文本的内容,但在德国Excel中它是一个浮点数。TimTom-一个非常简单的解决方案-仅供参考,我已经发布了我如何实际实现这一点以使其免费@simbabque-所有非常相关的要点;我们是全球性的,我可能必须找到一种方法,在不同的地区设置下运行这个程序,以确保我最大限度地正确修复每个部件。谢谢大家。