پیدا کنید، اصلاح کنید، اعتبارسنجی کنید: راهنمای کامل برای API جستجو، جایگزینی و لینک‌های خراب Aspose.Cells Cloud (.NET / Python / Java / cURL)

“کدام یک از ۴۰۰ کتاب کار بودجه ما هنوز می‌گوید Old Vendor Ltd؟” “هر placeholder {{COMPANY}} را در این الگو جایگزین کنید.” “آیا هیچ‌یک از گزارش‌های ما هنوز به آن دامنه‌ای که سال گذشته حذف کردیم لینک می‌دهد؟” — سه سؤال بسیار متفاوت، یک پاسخ مشترک: یک فراخوانی REST که صفحات گسترده را در ابر می‌خواند و بازنویسی می‌کند، بدون اینکه Excel در هیچ‌جایی نصب باشد.

مشکلات محتوا صفحه‌گسترده در تقریباً هر کدبیس سنگین‌داده ظاهر می‌شوند:

  • Content audit — یافتن هر سلول، شکل یا پیوندی که نام محصول منسوخ‌شده، آدرس قدیمی دفتر، یا نهاد قانونی منقضی‌شده‌ای را ذکر می‌کند؛
  • Template rendering — پر کردن توکن‌های {{PLACEHOLDER}} در تمام شیت‌ها قبل از ارسال یک ورک‌بوک به مشتری؛
  • Link rot — بررسی اینکه URLهای تعبیه‌شده در یک ورک‌بوک هنوز قابل دسترسی هستند، قبل از اینکه یک کار انطباق یا بایگانی آن را تأیید کند؛
  • Bulk correction — تصحیح یک اشتباه تایپی یا مقدار ستون غلط‌نویسی شده در ده‌ها شیت، یا محدود به تنها یک ناحیه از یک شیت.

گزینه‌های سنتی — یک کتابخانه اسکریپت‌نویسی که بر روی دستگاه خود اجرا می‌شود، یک ماکرو اکسل، یا یک کامپوننت COM بر روی سرور ویندوز — همگی به این معنا هستند که شما مسئول میزبانی و مقیاس‌پذیری منطق صفحه‌گسترده هستید. Aspose.Cells Cloud آن را به REST ساده تبدیل می‌کند: یک فایل (یا فقط نام فایل) ارسال کنید، تطبیق‌ها — یا یک فایل اصلاح‌شده — را دریافت کنید.

این پست به بررسی APIهای ارائه‌شده توسط SearchController اصلی در میکروسرویس Aspose.Cells Cloud می‌پردازد (منبع: src/Aspose.Cells.Cloud.MicroService/Controllers/SearchController.cs)، همراه با مثال‌های قابل اجرا در cURL و C# (.NET)، به‌علاوه نکاتی برای کاربران Python و Java.

1. کنترلر SearchController چه کاری می‌تواند انجام دهد؟

SearchController شامل سه خانواده قابلیت است که هر کدام در چندین محدوده موجود هستند:

Family What it does Mutates the workbook?
Search موارد متنی که با یک پرس‌وجو مطابقت دارند را برمی‌گرداند — همراه با موقعیت شیت و سلول/شکل/هایپرلینک آن‌ها خیر
Replace متن‌های مطابقت یافته را جایگزین می‌کند، سپس یا فایل اصلاح‌شده را به‌صورت جریان باز می‌گرداند یا آن را در ذخیره‌سازی ابری ذخیره می‌کند بله
Broken links هر پیوند http(s) موجود در کاربرگ را اعتبارسنجی می‌کند و مواردی که نتوانند حل شوند را برمی‌گرداند خیر

و هر خانواده در چهار دامنه در معرض قرار می‌گیرد، که در اینجا فهرست نقطه‌های انتهایی طولانی می‌شود:

دامنه جستجو جایگزینی لینک‌های خراب
فایل محلی → پردازش آنلاین (بارگذاری در بدنه درخواست) PUT /v4.0/cells/search/content PUT /v4.0/cells/replace/content PUT /v4.0/cells/search/broken-links
کل کتاب کار در ذخیره‌سازی ابری PUT /v4.0/cells/{name}/search/content PUT /v4.0/cells/{name}/replace/content PUT /v4.0/cells/{name}/search/broken-links
یک کاربرگ منفرد در ذخیره‌سازی ابری PUT /v4.0/cells/{name}/worksheets/{worksheet}/search/content PUT /v4.0/cells/{name}/worksheets/{worksheet}/replace/content PUT /v4.0/cells/{name}/worksheets/{worksheet}/search/broken-links
یک بازه منفرد در ذخیره‌سازی ابری PUT /v4.0/cells/{name}/worksheets/{worksheet}/ranges/{cellArea}/search/content PUT /v4.0/cells/{name}/worksheets/{worksheet}/ranges/{cellArea}/replace/content PUT /v4.0/cells/{name}/worksheets/{worksheet}/ranges/{cellArea}/search/broken-links

به‌علاوه دو نقطه انتهایی جایزه که هر مورد متنی را در یک کتاب کاری استخراج می‌کنند — ببینید §4:

هدف نقطه انتهایی
تمام موارد متن در یک فایل ابری PUT /v4.0/cells/{name}/search/content/all-textitems
تمام موارد متن در یک بارگذاری محلی PUT /v4.0/cells/search/content/all-textitems

یادداشت پیاده‌سازی: مسیرها با v{version:apiVersion}/cells پیشوند می‌شوند و این کنترلر [ApiVersion("4.0")] است، بنابراین تماس‌های زنده به شکل https://api.aspose.cloud/v4.0/cells/... ظاهر می‌شوند. همه چیز در این کنترلر یک PUT — حتی جستجوهای فقط‑خواندنی — زیرا یک جستجو به‌عنوان یک عملیات ارسال‌شده علیه یک منبع مدل‌سازی می‌شود، نه یک GET قابل کش.

دو حالت عملیاتی و دلیل اهمیت آن‌ها

کنترلر هر عمل را تزئین می‌کند و دکوراتور دقیقاً می‌گوید فایل از کجا می‌آید:

  • [OnlineOperation] — بی‌حالت. شما کاربرگ را در بدنه درخواست (multipart) آپلود می‌کنید، سرور آن را در حافظه پردازش می‌کند و هیچ‌کدام در ذخیره‌سازی ابری ذخیره نمی‌شود. برای “فقط بگو چه چیزی در این فایل است” و برای قالب‌سازی یک‌بار مصرف ایده‌آل است.
  • [CloudFileOperation] — پشتیبانی‌شده توسط ذخیره‌سازی. سرور {name} را از ذخیره‌سازی ابری دریافت می‌کند (به‌صورت اختیاری تحت folder=)، کار را انجام می‌دهد و — برای عملیات جایگزینی — نتیجه را مستقیماً باز می‌نویسد. هیچ‌چیزی به دستگاه شما منتقل نمی‌شود.

آن تمایز واحد، به‌همراه بخش‌های مسیر {worksheet} / {cellArea}، کل مدل ذهنی را تشکیل می‌دهد. بقیه این پست فقط جزئیات هستند.


۲. مدل‌های پاسخ که در واقعیت تجزیه می‌کنید

هر دو خانوادهٔ جستجو یک شکل کوچک، صاف و آسان برای بایندینگ برمی‌گردانند. جستجو SearchResponse را برمی‌گرداند:

{
  "Code": 200,
  "Status": "OK",
  "TextItems": [
    {
      "Filename": "Book1.xlsx",
      "Worksheet": "Q3 Forecast",
      "Position": "Cell:B7",
      "Content": "Old Vendor Ltd"
    },
    {
      "Filename": "Book1.xlsx",
      "Worksheet": "Q3 Forecast",
      "Position": "Shape:TextBox 3",
      "Content": "Prepared by Old Vendor Ltd"
    }
  ]
}

جستجوی لینک‌های خراب باز می‌گرداند BrokenLinksResponse:

{
  "Code": 200,
  "Status": "OK",
  "BrokenLinks": [
    {
      "Filename": "Book1.xlsx",
      "Worksheet": "Links",
      "Position": "Hyperlink:Sheet1!B4",
      "LinkAddress": "https://retired-domain.example.com/report"
    }
  ]
}

دو نکته بلافاصله شایسته اشاره هستند:

  1. Position یک مکان برچسب‌دار است, نه فقط یک آدرس سلول. پیشوند آن Cell:، Hyperlink: یا Shape: است، که این روش به یک فهرست صاف تک‌بعدی امکان می‌دهد بگوید چه نوع چیزی مطابقت داشته است. این برچسب تفاوت بین “fix cell B7” و “fix the text box sitting over B7” را ایجاد می‌کند.

  2. هر دو مدل برای گزارش‌گیری خودتوضیحی هستند — Filename و Worksheet برای هر آیتم برگردانده می‌شوند، بنابراین اسکن در میان بسیاری از کتاب‌کارها می‌تواند بدون پردازش پس از آن به یک جدول حسابرسی ترکیب شود.


3. دو موردی که قبل از شروع نیاز دارید

  1. در Aspose Cloud Dashboard یک حساب کاربری رایگان ثبت کنید و یک برنامه ایجاد کنید تا Client ID و Client Secret دریافت کنید (SDKها به‌صورت خودکار این موارد را برای یک JWT تعویض می‌کنند — نیازی به ساخت هدرهای احراز هویت به‌صورت دستی نیست).
  2. SDK را برای زبان مورد نظر خود نصب کنید:
<!-- .NET -->
<PackageReference Include="Aspose.Cells-Cloud" Version="25.x" />
# Python
pip install asposecellscloud
<!-- Java (Maven) — note: NOT on Maven Central, so the Aspose repo below is required -->
<repositories>
    <repository>
        <id>AsposeJavaAPI</id>
        <name>Aspose Java API</name>
        <url>https://repository.aspose.cloud/repo/</url>
    </repository>
</repositories>

<dependency>
    <groupId>com.aspose</groupId>
    <artifactId>aspose-cells-cloud</artifactId>
    <version>26.8</version>
</dependency>

نیازی به SDK نیست؟ همه چیز به صورت ساده REST است، بنابراین cURL نیز به همان اندازه کار می‌کند (به زیر نگاه کنید). خانواده جستجو/جایگزینی/لینک‌های خراب نیز از طریق مدل‌های درخواست SDK تایپ‌شده قابل دسترسی است — SearchSpreadsheetContentRequest، ReplaceContentInRemoteRangeRequest و دوستان — که همان چیزی است که قطعات کد C# زیر استفاده می‌کنند.


4. سناریو A: جستجوی یک فایل محلی به صورت آنلاین (بدون ذخیره‌سازی)

این PUT /v4.0/cells/search/content — کتاب‌کار را بارگذاری کنید، نتایج مطابقت را دریافت کنید. بدون ذخیره‌سازی ابری، بدون پاک‌سازی، بدون رونوشت باقی‌مانده.

① cURL

# 1) First, get a token
curl -X POST "https://api.aspose.cloud/connect/token" \
  -d "grant_type=client_credentials" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET"

# 2) Find "Old Vendor Ltd" anywhere in a local workbook
curl -X PUT "https://api.aspose.cloud/v4.0/cells/search/content" \
  -H "Authorization: Bearer $TOKEN" \
  --data-urlencode "searchText=Old Vendor Ltd" \
  --data-urlencode "ignoringCase=true" \
  -F "file=@Book1.xlsx"

آن را به یک صفحه یا به یک ناحیه از یک صفحه محدود کنید، با دو پارامتر پرس‌وجوی دیگر:

# Only "Q3 Forecast", only the range A1:F40
curl -X PUT "https://api.aspose.cloud/v4.0/cells/search/content" \
  -H "Authorization: Bearer $TOKEN" \
  --data-urlencode "searchText=Old Vendor Ltd" \
  --data-urlencode "worksheet=Q3 Forecast" \
  --data-urlencode "cellArea=A1:F40" \
  -F "file=@Book1.xlsx"

② C# / .NET

using Aspose.Cells.Cloud.SDK.Api;
using Aspose.Cells.Cloud.SDK.Request;

var cellsApi = new CellsApi("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET");

// Local file, whole workbook
var request = new SearchSpreadsheetContentRequest(
    spreadsheet:  "C:/audit/Book1.xlsx",   // local file path
    searchText:   "Old Vendor Ltd",
    ignoringCase: true);

SearchResponse response = cellsApi.SearchSpreadsheetContent(request);

foreach (var item in response.TextItems)
{
    Console.WriteLine($"{item.Worksheet} | {item.Position} | {item.Content}");
}
// Same call, scoped to one sheet and one range
var scoped = new SearchSpreadsheetContentRequest(
    spreadsheet:  "C:/audit/Book1.xlsx",
    searchText:   "Old Vendor Ltd",
    ignoringCase: true,
    sheetname:    "Q3 Forecast",
    cellarea:     "A1:F40");

مدل‌های درخواست همچنین password (باز کردن یک کتاب‌کار محافظت‌شده) و regoin (تنظیم منطقه/محلی) را در اختیار می‌گذارند — همان پارامترهای اختیاری که در انواع cloud‑storage به عنوان storageName می‌بینید. توجه داشته باشید که SDK .NET نوشتار regoin را حفظ می‌کند؛ SDK پایتون همان دو تنظیم password و region را نام می‌برد.

③ پایتون / جاوا

SDK پایتون همان خانوادهٔ نقطهٔ انتهایی را می‌پیچاند، به‌طوری که فیلدهای مدل درخواست به‌صورت یک به یک به فیلدهای C# نگاشته می‌شوند، اما به صورت snake_case:

from asposecellscloud.apis.cells_api import CellsApi
from asposecellscloud.requests import (
    SearchSpreadsheetContentRequest,
    SearchContentInRemoteRangeRequest,
)

instance = CellsApi("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET")

# Local upload — returned items carry Worksheet / Position / Content
local = instance.search_spreadsheet_content(
    SearchSpreadsheetContentRequest(
        "Book1.xlsx", "Old Vendor Ltd",
        ignoring_case=True, worksheet="Q3 Forecast", cell_area="A1:F40"))

# Range-scoped search of a file already in cloud storage
remote = instance.search_content_in_remote_range(
    SearchContentInRemoteRangeRequest(
        "Book1.xlsx", "Q3 Forecast", "A1:F40", "Old Vendor Ltd",
        ignoring_case=True, folder="Reports"))

for item in remote.text_items:
    print(item.worksheet, item.position, item.content)

SDK جاوا همان شکل را دنبال می‌کند که اشیاء Request از طریق setterها ساخته می‌شوند:

import com.aspose.cloud.cells.api.CellsApi;
import com.aspose.cloud.cells.model.SearchResponse;
import com.aspose.cloud.cells.request.SearchContentInRemoteRangeRequest;

public class SearchDemo {
    public static void main(String[] args) throws Exception {
        CellsApi api = new CellsApi("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET");

SearchContentInRemoteRangeRequest req = new SearchContentInRemoteRangeRequest();
        req.setName("Book1.xlsx");
        req.setWorksheet("Q3 Forecast");
        req.setCellArea("A1:F40");
        req.setSearchText("Old Vendor Ltd");
        req.setIgnoringCase(true);
        req.setFolder("Reports");

SearchResponse response = api.searchContentInRemoteRange(req);
        response.getTextItems().forEach(i ->
            System.out.println(i.getWorksheet() + " | " + i.getPosition() + " | " + i.getContent()));
    }
}

اگر از REST خام استفاده می‌کنید، cURL بالا قرارداد کامل است — فیلد multipart فقط باید نام فایل را حمل کند، زیرا سرویس نام کتاب‌کار (و در نتیجه فرمت آن) را از آن استخراج می‌کند.


5. سناریو B: جستجوی فایلی که قبلاً در فضای ذخیره‌سازی ابری وجود دارد

وقتی کتاب‌کار قبلاً در Aspose Cloud Storage موجود است، به‌طور کامل دانلود را نادیده بگیرید — سرویس آن را از همان جایی که قرار دارد می‌خواند:

# Whole workbook
curl -X PUT "https://api.aspose.cloud/v4.0/cells/Book1.xlsx/search/content" \
  -H "Authorization: Bearer $TOKEN" \
  --data-urlencode "searchText=Old Vendor Ltd" \
  --data-urlencode "ignoringCase=true" \
  --data-urlencode "folder=Reports"

# Just one worksheet
curl -X PUT "https://api.aspose.cloud/v4.0/cells/Book1.xlsx/worksheets/Q3%20Forecast/search/content" \
  -H "Authorization: Bearer $TOKEN" \
  --data-urlencode "searchText=Old Vendor Ltd"

# Just one range of one worksheet
curl -X PUT "https://api.aspose.cloud/v4.0/cells/Book1.xlsx/worksheets/Q3%20Forecast/ranges/A1:F40/search/content" \
  -H "Authorization: Bearer $TOKEN" \
  --data-urlencode "searchText=Old Vendor Ltd"
// Whole workbook in storage
var response = cellsApi.SearchContentInRemoteSpreadsheet(
    new SearchContentInRemoteSpreadsheetRequest(
        name:         "Book1.xlsx",
        searchText:   "Old Vendor Ltd",
        ignoringCase: true,
        folder:       "Reports"));

// One worksheet
var sheetHits = cellsApi.SearchContentInRemoteWorksheet(
    new SearchContentInRemoteWorksheetRequest(
        name:       "Book1.xlsx",
        sheetname:  "Q3 Forecast",
        searchText: "Old Vendor Ltd",
        folder:     "Reports"));

// One range
var rangeHits = cellsApi.SearchContentInRemoteRange(
    new SearchContentInRemoteRangeRequest(
        name:        "Book1.xlsx",
        sheetname:   "Q3 Forecast",
        cellArea:    "A1:F40",
        searchText:  "Old Vendor Ltd",
        ignoringCase: true,
        folder:      "Reports"));

چرا سه نقطه انتهایی به جای یک؟ زیرا مسیر محدوده را حمل می‌کند. نقطه انتهایی whole-workbook یک نام و یک پرس‌وجو می‌گیرد؛ نقطه انتهایی worksheet یک بخش از برگه کاری می‌گیرد؛ نقطه انتهایی range یک برگه کاری و یک بخش محدوده می‌گیرد. این یک ساختار REST تمیز و قابل کش است — و به این معنی است که پارامترهای «محدود کردن جستجو» (worksheet, cellArea) فقط در نقطه انتهایی local-file وجود دارند، که هنگام انتقال یک فراخوانی از یک محدوده به محدوده دیگر، به یاد داشتن آن ارزش دارد.

6. سناریو C: دریافت هر مورد متن در یک کتاب‌کار

گاهی اوقات شما یک عبارت جستجو ندارید — شما موجودی را می‌خواهید. نقاط انتهایی all-textitems هر مورد متن را در کتاب کار برمی‌گردانند، بنابراین می‌توانید دو نسخه را مقایسه کنید، یک واژه‌نامه ترجمه بسازید یا یک ایندکس‌کننده را تغذیه کنید:

# Cloud file — every text item
curl -X PUT "https://api.aspose.cloud/v4.0/cells/Book1.xlsx/search/content/all-textitems" \
  -H "Authorization: Bearer $TOKEN" \
  --data-urlencode "folder=Reports"

# Local upload — every text item
curl -X PUT "https://api.aspose.cloud/v4.0/cells/search/content/all-textitems" \
  -H "Authorization: Bearer $TOKEN" \
  -F "file=@Book1.xlsx"

پاسخ همان پاکت SearchResponse است، به‌طوری که Content برای هر رشته سلول، عنوان پیوند و متن شکل در فایل پر شده است. این یک primitive برای “grep the whole workbook” است.

7. سناریو D: جایگزینی — و دو نتیجه بسیار متفاوت

جایگزینی جایی است که API به دو بخش تقسیم می‌شود و این تقسیم عمدی است:

بارگذاری محلی → دانلود فایل اصلاح‌شده فایل ابری → دوباره در ذخیره‌سازی ذخیره شد
نقطه انتهایی PUT /v4.0/cells/replace/content PUT /v4.0/cells/{name}/replace/content
بازگشت یک جریان فایل (همان فرمت که آپلود کردید) CellsCloudResponse { "Code": 200, "Status": "OK" }
ذخیره‌سازی تحت تأثیر هیچ‌کدام فایل اصلی بازنویسی می‌شود

① جایگزینی در یک کتاب‌کار محلی، نتایج را به‌صورت جریان بازگردانید

curl -X PUT "https://api.aspose.cloud/v4.0/cells/replace/content" \
  -H "Authorization: Bearer $TOKEN" \
  --data-urlencode "searchText={{COMPANY}}" \
  --data-urlencode "replaceText=Northwind Traders" \
  -F "file=@template.xlsx" \
  -o template-rendered.xlsx
using Aspose.Cells.Cloud.SDK.Request;

var request = new ReplaceSpreadsheetContentRequest(
    spreadsheet: "C:/templates/template.xlsx",
    searchText:  "{{COMPANY}}",
    replaceText: "Northwind Traders");

// Option A: get the corrected workbook as a Stream
using Stream corrected = cellsApi.ReplaceSpreadsheetContent(request);
using var outFile = File.Create("C:/templates/template-rendered.xlsx");
corrected.CopyTo(outFile);

// Option B: let the SDK write it for you (.NET overload with an output path)
// cellsApi.ReplaceSpreadsheetContent(request, "C:/templates/template-rendered.xlsx");

در اینجا همچنین دو پارامتر دامنه موجود است — sheetname و cellarea — تا بتوانید جای‌نگهدارها را در یک شیت رندر کنید بدون اینکه به بقیهٔ قالب دست بزنید.

② جایگزینی در یک دفتر کار ابری، نگهداری آن در محل

# Whole workbook, saved back to storage
curl -X PUT "https://api.aspose.cloud/v4.0/cells/Book1.xlsx/replace/content" \
  -H "Authorization: Bearer $TOKEN" \
  --data-urlencode "searchText=Old Vendor Ltd" \
  --data-urlencode "replaceText=Northwind Traders" \
  --data-urlencode "folder=Reports"

# One worksheet
curl -X PUT "https://api.aspose.cloud/v4.0/cells/Book1.xlsx/worksheets/Q3%20Forecast/replace/content" \
  -H "Authorization: Bearer $TOKEN" \
  --data-urlencode "searchText=Old Vendor Ltd" \
  --data-urlencode "replaceText=Northwind Traders" \
  --data-urlencode "folder=Reports"

# One range
curl -X PUT "https://api.aspose.cloud/v4.0/cells/Book1.xlsx/worksheets/Q3%20Forecast/ranges/A1:F40/replace/content" \
  -H "Authorization: Bearer $TOKEN" \
  --data-urlencode "searchText=Old Vendor Ltd" \
  --data-urlencode "replaceText=Northwind Traders" \
  --data-urlencode "folder=Reports"
// Whole workbook — result saved back into cloud storage
cellsApi.ReplaceContentInRemoteSpreadsheet(
    new ReplaceContentInRemoteSpreadsheetRequest(
        name:        "Book1.xlsx",
        searchText:  "Old Vendor Ltd",
        replaceText: "Northwind Traders",
        folder:      "Reports"));

// Range-scoped
cellsApi.ReplaceContentInRemoteRange(
    new ReplaceContentInRemoteRangeRequest(
        name:        "Book1.xlsx",
        searchText:  "Old Vendor Ltd",
        replaceText: "Northwind Traders",
        worksheet:   "Q3 Forecast",
        cellarea:    "A1:F40",
        folder:      "Reports"));

جایگزینی در محل به‌صورت مخرب طراحی شده است. نسخه‌های ابری {name} را بازنویسی می‌کنند — هیچ نسخهٔ پشتیبانی ساخته نمی‌شود. برای جریان‌های کاری با تمرکز بر حسابرسی، یک نسخهٔ بازنگری‌شده نگه دارید (مثلاً ابتدا Book1-2026-09-11.xlsx را بارگذاری کنید، سپس جایگزین کنید) یا از نسخهٔ بارگذاری محلی استفاده کنید و جریان بازگشتی را خودتان ذخیره کنید.


8. Scenario E: پیدا کردن پیوندهای خراب پیش از اینکه شخص دیگری انجام دهد

بررسی پیوندها ویژگی پنهانی اینجا است — این همان چیزی است که نوشتن آن به‌صورت دستی خسته‌کننده است و نادیده گرفتن آن خجالت‌آور. چهار دامنهٔ مختلف در دسترس هستند؛ نسخهٔ فایل‑محلی سریع‌ترین بررسی صحت است:

# Local workbook, whole file
curl -X PUT "https://api.aspose.cloud/v4.0/cells/search/broken-links" \
  -H "Authorization: Bearer $TOKEN" \
  -F "file=@Book1.xlsx"

# Cloud workbook, whole file
curl -X PUT "https://api.aspose.cloud/v4.0/cells/Book1.xlsx/search/broken-links" \
  -H "Authorization: Bearer $TOKEN" \
  --data-urlencode "folder=Reports"

# Cloud workbook, one worksheet
curl -X PUT "https://api.aspose.cloud/v4.0/cells/Book1.xlsx/worksheets/Links/search/broken-links" \
  -H "Authorization: Bearer $TOKEN" \
  --data-urlencode "folder=Reports"
var broken = cellsApi.SearchSpreadsheetBrokenLinks(
    new SearchSpreadsheetBrokenLinksRequest(
        spreadsheet: "C:/audit/Book1.xlsx"));

foreach (var link in broken.BrokenLinks)
{
    Console.WriteLine($"{link.Worksheet} {link.Position} -> {link.LinkAddress}");
}

نتیجه یک فهرست است که می‌توانید مستقیماً روی آن عمل کنید: هر ورودی نام شیت، موقعیت و LinkAddress مشکل‌دار را نشان می‌دهد.

9. در واقع چه چیزی اسکن می‌شود؟ (جزئیات پیاده‌سازی که انتظارات شما را تغییر می‌دهد)

این بخشی است که یک ادغام کارآمد را از یک ادغام شگفت‌انگیز جدا می‌کند. با خواندن WorkbookExtension.cs، یک جستجو سه نوع عنصر متمایز را در هر کاربرگ پیمایش می‌کند:

نوع عنصر منبع چیزی که مطابقت دارد برچسب Position
رشته‌های سلول worksheet.Cells مقدار رشته‌ای سلول Cell:A1
هایپرلینک‌ها worksheet.Hyperlinks هم آدرس address و متن display text Hyperlink:Sheet1!B4
اشکال worksheet.Shapes shape.Text — جعبه‌های متن، فراخوانی‌ها، برچسب‌ها Shape:TextBox 3

و اینجا رفتارهایی که ارزش دانستن دارند قبل از طراحی دور آنها:

فقط سلول‌های رشته‌ای جستجو می‌شوند. اسکن بر پایهٔ CellValueType.IsString فیلتر می‌شود. سلولی که شامل یک عدد، یک تاریخ یا یک بولی باشد، نادیده گرفته می‌شود — بنابراین جستجوی 2025 با سلول تاریخ‌دار که مقدار سریالی آن به طور تصادفی 2025 است، مطابقت نخواهد داشت. سلول‌هایی که فرمول‌هایشان به متن ارزیابی می‌شود، مطابقت دارند، زیرا نوع مقدار آن‌ها رشته است.

حساسیت به حروف بزرگ/کوچک تنها گزینهٔ مطابقت است. ignoringCase بین مقایسهٔ InvariantCultureIgnoreCase و InvariantCulture سوئیچ می‌کند — و هیچ چیز دیگری نیست. هیچ حالت «کلمهٔ کامل»، «عبارت منظم» یا “مطابقت تمام مقدار سلول” وجود ندارد، حتی اگر مستندات API تولید شده این را القا کنند. اگر به این معناها نیاز دارید، موجودی all-textitems را دریافت کنید و آن را در سمت خود فیلتر کنید.

جایگزینی ساده، حساس به حروف بزرگ و کوچک، جایگزینی متنی است. پرچم ignoringCase در جستجو معادل‌ای در جایگزینی ندارد — مسیر جایگزینی هیچ پارامتر عدم حساسیت به حروف بزرگ و کوچک ندارد. و دو مسیر کد به‌صورت داخلی متفاوت هستند: یک جایگزینی کل‌ورق کاری به موتور Worksheet.Replace(...) واگذار می‌شود، در حالی که یک جایگزینی محدوده‌ای، محدوده را پیمایش می‌کند و هر سلول متنی را با cell.StringValue.Replace(...) بازنویسی می‌کند. نتیجهٔ عملی: جایگزینی محدوده‌ای فقط بر سلول‌های متنی تأثیر می‌گذارد، و این جایگزینی متنی است، نه مبتنی بر الگو.

تطبیق‌های پیوند، آدرس را گزارش می‌دهند، نه عنوان. هنگامی که جستجو متن نمایش یک پیوند را تطبیق می‌دهد، مقدار بازگردانده شده Content همچنان hyperlink.Address است. اگر در حال تولید گزارشی به شکل «در اینجا پیدا شد» هستید، انتظار URL را داشته باشید — عنوان بازگردانده نمی‌شود.

بررسی لینک‌های خراب فقط http:// و https:// را بررسی می‌کند. لینک‌های mailto:، مسیرهای فایل محلی و انکرهای داخلی #Sheet1!A1 به‌طور کامل نادیده گرفته می‌شوند — آنها هرگز تست نمی‌شوند، بنابراین هرگز در نتایج ظاهر نمی‌شوند. همچنین پیوندهای ابرمتنی پیوست شده به شکل‌ها و سلول‌ها را اسکن می‌کند، که دقیقاً جایی است که لینک‌های خراب تمایل به مخفی شدن دارند. توجه داشته باشید که Position یک لینک خراب از hyperlink.Area خام ساخته می‌شود (نه از Area.ToRangName() کاربرپسندتری که نقاط انتهایی جستجو استفاده می‌کنند)، بنابراین فرض نکنید که دو خانواده موقعیت‌ها را به‌صورت یکسان رندر می‌کنند — اگر به یک کلید ثابت نیاز دارید، جفت Worksheet + LinkAddress را تجزیه کنید.

“Broken” به معنی “قابل دسترسی نیست”، نه “کد وضعیت اشتباه”. بررسی یک درخواست HTTP HEAD برای هر لینک ارسال می‌کند و هر پاسخی — شامل 404 یا 500 — را به عنوان قابل دسترسی در نظر می‌گیرد؛ فقط زمانی لینک را خراب علامت می‌زند که درخواست خطا می‌دهد (خطای DNS، اتصال رد شده، خطای TLS، timeout). بنابراین خروجی را به عنوان “لینک‌هایی که قابل تماس نیستند” در نظر بگیرید. اگر آنچه واقعاً نیاز دارید “لینک‌هایی که 2xx برنمی‌گردانند” باشد، می‌خواهید مقادیر LinkAddress بازگردانده شده را خودتان دوباره بررسی کنید.

cellArea پذیرفته می‌شود اما در نقاط انتهایی broken‑link اعمال نمی‌شود. پیاده‌سازی BrokenLinks فقط بر اساس نام worksheet فیلتر می‌کند؛ آرگومان cell‑area ارسال می‌شود اما هرگز استفاده نمی‌شود. در عمل این به این معنی است که .../ranges/A1:F40/search/broken-links در حال حاضر همان رفتار را دارد که /worksheet/search/broken-links برای همان worksheet — لینک‌ها در تمام شیت اعتبارسنجی می‌شوند. گزارش‌های reports خود را متناسب تنظیم کنید (یا لیست بازگشتی را بر اساس موقعیت فیلتر کنید) به جای این‌که فرض کنید محدوده بررسی را محدود می‌کند.

هیچ‌یک از این‌ها مانع نیستند — آن‌ها تفاوت بین ویژگی‌ای که “در نسخهٔ نمایشی کار می‌کند” و ویژگی‌ای که به‌صورت پیش‌بینی‌شده در محیط تولید رفتار می‌کند، هستند.

10. مدیریت خطا و نکات عملیاتی

قراردادی که کنترلر مستند می‌کند

وضعیت معنی دلیل معمول
400 درخواست نامعتبر آدرس/پارامترهای نامعتبر — به عنوان مثال cellArea نادرست یا عدم وجود searchText
401 غیرمجاز احراز هویت ناموفق بود یا هیچ اعتبار معتبر ارائه نشد
404 یافت نشد فایل منبع در ذخیره‌سازی ابری قابل دسترسی نیست
500 خطای سرور سرویس هنگام دریافت داده‌های صفحه‌گسترده با یک ناهماهنگی مواجه شد

به‌صورت داخلی، هر عمل کار خود را در یک کمک‌کننده (WorkbookElementOperation, UpdateWorkbookElementOperation, UpdateWorkbookElementOperationAndSave) می‌پیچد که خطاها را می‌گیرد و به‌عنوان یک CellsApiException با پیشوند نام عملیات دوباره پرتاب می‌کند — برای مثال SearchContentInRemoteRange Error Message: .... آن نام عملیات رشته‌ای است که در لاگ‌های شما مشاهده خواهید کرد:

نام عملیات خانواده نقطه انتهایی
SearchSpreadsheetContent, SearchContentInRemoteSpreadsheet جستجوی محلی / از راه دور
SearchContentInRemoteWorksheet, SearchContentInRemoteRange جستجوی محدوده‌ای از راه دور
ReplaceSpreadsheetContent جایگزینی محلی (نتیجه به‌صورت جریان)
ReplaceContentInRemoteSpreadsheet, ReplaceContentInRemoteWorksheet, ReplaceContentInRemoteRange جایگزینی از راه دور (نتیجه ذخیره می‌شود)
SearchSpreadsheetBrokenLinks, SearchBrokenLinksInRemoteSpreadsheet, SearchBrokenLinksInRemoteWorksheet, SearchBrokenLinksInRemoteRange اعتبارسنجی پیوند

پارامترهای اختیاری که SDKها در دسترس می‌گذارند

علاوه بر پارامترهای مستند شده، تمام مدل‌های درخواست ذخیره‌سازی ابری همان سه تنظیمات اختیاری را دارند:

  • password — یک کتاب‌کار محافظت‌شده با رمز عبور را باز می‌کند (جستجوها نیازی به دسترسی نوشتن ندارند، بنابراین فایل‌های فقط‑خواندنی به‌خوبی کار می‌کنند);
  • storageName — به‌جای ذخیره‌ساز پیش‌فرض، یک ذخیره‌ساز ابری سفارشی/پیوست‌شده را هدف می‌گیرد (Python: storage_name);
  • regoin — تنظیمات منطقه/محلی که هنگام تفسیر کتاب‌کار استفاده می‌شود (در Python این به صورت region نوشته می‌شود).

احراز هویت

تمام SDKها به‌صورت خودکار با OAuth 2.0 client_credentials و یک JWT احراز هویت می‌شوند؛ هنگام استفاده از cURL خام، ابتدا یک‌بار /connect/token را فراخوانی کنید (به §4، ① مراجعه کنید).

11. چرا Aspose.Cells Cloud برای جستجو و جایگزینی؟

  • ✅ بدون وابستگی‌های محلی — بدون Office/Excel، بدون COM، بدون میزبان اسکریپت‌نویسی. قابل فراخوانی از هر زبان، هر پلتفرم (Linux، کانتینرها، سرورلس)؛
  • ✅ عمیق‌تر از جستجوی متن — سلول‌ها، شکل‌ها و هایپرلینک‌ها همگی هدف‌های جستجوی درجه یک هستند، که دقیقاً جایی است که صفحات گسترده واقعی محتواهای خود را نگه می‌دارند؛
  • ✅ عملیات محدوده‌ای — کتاب کار / برگه کاری / بازه، بنابراین می‌توانید یک ناحیه از یک شیت را بدون بازنویسی یک فایل ۵۰ مگابایتی اصلاح کنید؛
  • ✅ ابری‑محلی یا بدون حالت — فایل‌های موجود در ذخیره‌سازی هرگز آن را ترک نمی‌کنند؛ عملیات بارگذاری محلی هیچ چیزی را ذخیره نمی‌کند؛
  • ✅ بازنویسی با دقت بالا — جایگزین‌ها از طریق موتور Aspose.Cells اعمال و دوباره سریال‌سازی می‌شوند، بنابراین فرمول‌ها، سبک‌ها، نمودارها و قالب‌بندی‌ها در مسیر رفت و برگشت زنده می‌مانند؛
  • ✅ یک شکل در تمام SDKها — سطوح cURL، .NET، Python و Java به‌صورت ۱:۱ نگاشت می‌شوند، بنابراین الگوی که از یک زبان کپی می‌کنید در دیگران کار می‌کند.

همین حالا شروع کنید: در Aspose Cloud Dashboard ثبت‌نام کنید، یک Application ایجاد کنید، اعتبارنامه‌های خود را در هر اسنیپت بالا بگذارید، و آن را به یکی از دفترچه‌های کاری خود اشاره کنید — در عرض چند دقیقه یک بررسی محتوا کارآمد خواهید داشت.

آیا این مفید بود؟ ستاره بگذارید، بوکمارک کنید یا آن را به اشتراک بگذارید — و در نظرات بگویید برای چه کاری از جستجو و جایگزینی در کتاب‌کار استفاده می‌کنید.