مقاله فنی

دیف‌کردن دو کارپوشه اکسل در دلفی با HotXLS

HotXLS دو کارپوشه را از طریق TXLSXWorkbookCompare مقایسه می‌کند، که کاربرگ‌ها را بر اساس نام جفت می‌کند، سلول‌های پرشده هر جفت را می‌پیماید، و آنچه را که متفاوت است به‌صورت یک فهرست ساختاریافته از رکوردهای تفاوت و، در صورت درخواست، به‌صورت یک خط قابل‌خواندن به ازای هر تفاوت گزارش می‌دهد. هیچ نصب اکسلی درگیر نیست، و مقایسه کاملاً روی مدل شیء بارگذاری‌شده در دلفی یا C++Builder اجرا می‌شود

این نیاز معمولاً اولین‌باری که کسی می‌پرسد چه چیزی تغییر کرده، ظاهر می‌شود. یک کارپوشه مالی از بازبینی بازمی‌گردد، یک صادرات شبانه پس از یک تغییر کد دوباره تولید می‌شود، یا دو بخش نسخه‌هایی از یک قالب واحد ارسال می‌کنند. بازکردن هر دو کنار هم برای یک کاربرگ کار می‌کند و برای بیست کاربرگ شکست می‌خورد. مقایسه فایل‌ها بایت به بایت اصلاً به هیچ چیزی پاسخ نمی‌دهد، زیرا دو ذخیره‌سازی از یک کارپوشه واحد به شیوه‌هایی متفاوت‌اند که هیچ‌کس اهمیتی به آن‌ها نمی‌دهد

چه چیزی به‌عنوان تفاوت حساب می‌شود؟

مقایسه هشت نوع را گزارش می‌دهد، و این مجموعه به‌عمد کوچک است: یک کاربرگ افزوده یا حذف‌شده، یک سلول پرشده افزوده یا حذف‌شده، یک سلول که مقدارش تغییر کرده، یک سلول که فرمولش تغییر کرده، و یک بازه ادغام‌شده افزوده یا حذف‌شده. همه‌چیز نسبت به کارپوشه چپ به‌عنوان خط مبنا بیان می‌شود، بنابراین یک مورد افزوده فقط در سمت راست وجود دارد و یک مورد حذف‌شده فقط در سمت چپ

کاربرگ‌ها بر اساس نام جفت می‌شوند نه بر اساس موقعیت. بنابراین ترتیب مجدد کاربرگ‌ها اصلاً هیچ تفاوتی تولید نمی‌کند، که تقریباً همیشه همان رفتاری است که می‌خواهید: کاربری که یک تب را می‌کشد، یک تغییر داده نیست. کاربرگی که فقط در یک سمت حضور دارد، یک ورودی سطح‌کاربرگ واحد گزارش می‌دهد، به‌جای بسط هر سلول پرشده درون آن، که یک گزارش از دو کارپوشه ساختاراً متفاوت را قابل‌خواندن نگه می‌دارد به‌جای هزاران خط طولانی

مقدار یا فرمول، و هرکدام چگونه مقایسه می‌شود؟

هر سلول یک امضا مشارکت می‌دهد، و قاعده ساده است: سلولی که یک فرمول حمل می‌کند بر اساس متن فرمول خود با یک علامت مساوی پیشرو مقایسه می‌شود، و سلولی که فرمول ندارد بر اساس مقدار خود تبدیل‌شده به متن مقایسه می‌شود. این تمایز بیشتر از آنچه در نگاه اول به نظر می‌رسد، اهمیت دارد. دو سلول می‌توانند همان عدد نمایش‌داده‌شده را داشته باشند درحالی‌که یکی لفظی است و دیگری فرمول، و برابر در نظرگرفتن آن‌ها دقیقاً همان ویرایشی را که بیشترین ارزش گرفتار‌شدن را در یک کارپوشه بازبینی‌شده دارد، پنهان می‌کند

این همچنین یعنی فرمولی که متنش تغییر نکرده هیچ تفاوتی گزارش نمی‌دهد حتی اگر نتیجه ذخیره‌شده‌اش متفاوت باشد، که رفتار درست برای مقایسه محتوای تألیف‌شده است، و رفتار نادرست اگر می‌خواهید انحراف محاسبه مجدد را تشخیص دهید. برای آن پرسش دوم، هر دو کارپوشه را پیش از مقایسه دوباره محاسبه کنید، تا مقادیری که مقایسه می‌کنید همان‌هایی باشند که فرمول‌ها امروز واقعاً تولید می‌کنند

اجرای یک مقایسه

Compare دو کارپوشه بارگذاری‌شده می‌گیرد و تعداد تفاوت‌های یافت‌شده را برمی‌گرداند. فهرست تفاوت‌ها سپس بر اساس اندیس در دسترس است، یا می‌تواند در هر TStringsای ریخته شود:

uses
  lxHandleX, lxCompare;

var
  Left, Right: TXLSXWorkbook;
  Cmp: TXLSXWorkbookCompare;
  Lines: TStringList;
begin
  Left := TXLSXWorkbook.Create;
  Right := TXLSXWorkbook.Create;
  Cmp := TXLSXWorkbookCompare.Create;
  Lines := TStringList.Create;
  try
    if (Left.Open('baseline.xlsx') <> 1) or
       (Right.Open('reviewed.xlsx') <> 1) then
      Exit;

    if Cmp.Compare(Left, Right) = 0 then
      Writeln('workbooks are equivalent')
    else
    begin
      Cmp.Report(Lines);              // یک خط قابل‌خواندن به ازای هر تفاوت
      Lines.SaveToFile('workbook-diff.txt');
      Writeln(Format('%d difference(s) written', [Cmp.Count]));
    end;
  finally
    Lines.Free;
    Cmp.Free;
    Right.Free;
    Left.Free;
  end;
end;

خطی که Report تولید می‌کند مثل value changed: Data!A2: 10 -> 99 خوانده می‌شود، که برای یک بازبین کافی است و برای یک پیام کامیت کافی است. این سطح روبه‌انسان است. سطح برنامه‌نویسی خودِ رکورد تفاوت است، و این همان چیزی است که باید استفاده شود وقتی مقایسه یک تصمیم را تغذیه می‌کند نه یک سند

هدایت منطق از تفاوت‌های ساختاریافته

هر تفاوت نوع خود، نام کاربرگ، سطر و ستون یک‌پایه برای ورودی‌های سطح‌سلول، یک ارجاع A1 برای ورودی‌های سطح‌ادغام، و متن چپ و راست را افشا می‌کند. ورودی‌های سطح‌کاربرگ و سطح‌ادغام، سطر و ستون را صفر گزارش می‌دهند، که همان روشی است که بدون بررسی نوع، آن‌ها را از هم تشخیص می‌دهید:

var
  I: Integer;
  D: TlxCompareDiff;
  FormulaEdits: Integer;
begin
  FormulaEdits := 0;
  for I := 0 to Cmp.Count - 1 do
  begin
    D := Cmp.Diff(I);
    case D.Kind of
      lckFormulaChanged:
        begin
          Inc(FormulaEdits);
          Writeln(Format('%s R%dC%d: %s => %s',
            [D.Sheet, D.Row, D.Col, D.LeftText, D.RightText]));
        end;
      lckSheetAdded, lckSheetRemoved:
        Writeln(Format('structure: %s', [D.Describe]));
      lckMergeAdded, lckMergeRemoved:
        Writeln(Format('layout: %s at %s', [D.Describe, D.Ref]));
    end;
  end;

  // یک خط‌مشی بازبینی که فقط روی ویرایش فرمول مسدود می‌کند
  if FormulaEdits > 0 then
    raise Exception.CreateFmt(
      '%d formula change(s) need sign-off', [FormulaEdits]);
end;

دو ویژگی از خروجی پیش از نوشتن ادعاها در برابر آن ارزش دانستن دارند. ترتیب ورودی‌های سطح‌سلول از ترتیب پیمایش داخلی مخزن سلول پیروی می‌کند، بنابراین آزمون‌ها باید مستقل از ترتیب نوشته شوند. و امضای فرمول علامت مساوی پیشرو مخصوص به خود را حمل می‌کند، که به این معناست که یک رشته توصیفی ساخته‌شده با الحاق می‌تواند یک == دوتایی نشان دهد؛ وقتی نتیجه منطق را هدایت می‌کند، مقادیر فیلد را بررسی کنید نه تجزیه خط توصیفی

دیف‌کردن کارپوشه کجا سودمند است؟

سه کاربرد به‌تنهایی این ویژگی را توجیه می‌کنند. آزمون رگرسیون یک موتور گزارش‌سازی: یک کارپوشه شناخته‌شده‌درست را نگه دارید، دوباره تولید کنید، مقایسه کنید، و ساخت را در برابر هر تفاوت غیرمنتظره‌ای شکست دهید. بازبینی تغییر: به یک بازبین گزارش قابل‌خواندن بدهید به‌جای دو فایل. و تأیید مهاجرت: پس از تبدیل یک دسته کارپوشه قدیمی، هر نتیجه را در برابر منبعش مقایسه کنید تا ثابت شود چیزی از دست نرفته

آن مورد سوم به‌طور طبیعی با گذرهای موجودی‌گیری و ممیزی که در میزکار ممیزی و تبدیل کارپوشه شرح داده شده جفت می‌شود، جایی که شمارش آنچه یک کارپوشه دارد پیش از تبدیل رخ می‌دهد و مقایسه پس از آن. اگر تفاوت‌های شما حول ردیف‌های درج‌شده خوشه می‌بندند، قواعد بازنویسی ارجاع در تعدیل ارجاع فرمول هنگام درج و حذف توضیح می‌دهند چرا فرمول‌هایی که تغییرنیافته به نظر می‌رسند، تغییریافته گزارش می‌شوند

محدودیت‌ها، به‌صراحت بیان‌شده

مقایسه مقادیر، فرمول‌ها، ادغام‌ها و حضور کاربرگ را پوشش می‌دهد. قالب‌های عددی، فونت‌ها، پرکردن‌ها، قواعد قالب‌بندی شرطی، اعتبارسنجی‌های داده، نمودارها، تصاویر یا نام‌های تعریف‌شده را مقایسه نمی‌کند. سلولی که مقدارش یکسان اما قالبش از General به Currency تغییر کرده، هیچ تفاوتی گزارش نمی‌دهد، که برای یک مقایسه داده‌ای درست است و برای یک بازبینی قالب‌بندی ناکافی است

سلول‌های دارای مقدار تاریخ یک هشدار خاص را می‌طلبند: آن‌ها به‌صورت تبدیل متنی خود مقایسه می‌شوند، بنابراین کارپوشه‌ای که روی سیستم تاریخ ۱۹۰۴ ذخیره شده و کارپوشه‌ای روی سیستم ۱۹۰۰، می‌توانند به شیوه‌هایی که اگر اعداد ترتیبی زیرین متفاوت باشند شما را غافلگیر می‌کنند، برابر یا نابرابر مقایسه شوند. قواعد سیستم تاریخ در اعداد ترتیبی تاریخ و سیستم ۱۹۰۴ پوشش داده شده. وقتی وفاداری قالب‌بندی یا سطح‌شیء بخشی از پرسش است، دیف را با یک گذر ممیزی که آن ویژگی‌ها را در هر سمت می‌شمارد ترکیب کنید

مقایسه کارپوشه، ممیزی و تبدیل همگی روی یک موتور واحد برای دلفی و C++Builder اجرا می‌شوند؛ فهرست کامل ویژگی‌ها در صفحه مؤلفه صفحه‌گسترده HotXLS برای دلفی قرار دارد