찾아라, 고쳐라, 검증하라: Aspose.Cells Cloud 검색, 교체 및 깨진 링크 API에 대한 완전 가이드 (.NET / Python / Java / cURL)

“우리 400개의 예산 워크북 중 아직도 _Old Vendor Ltd_라고 표시된 것이 있나요?” “이 템플릿의 모든 {{COMPANY}} 자리표시자를 교체하세요.” “우리 보고서 중 아직도 작년 퇴역한 도메인에 연결된 것이 있나요?” — 매우 다른 세 질문이지만, 공통된 답은 클라우드에서 스프레드시트를 읽고 다시 쓰는 REST 호출이며, 어디에도 Excel이 설치되어 있지 않습니다.

스프레드시트 콘텐츠 문제는 거의 모든 데이터 중심 코드베이스에서 나타납니다:

  • Content audit — 사용되지 않는 제품 이름, 오래된 사무실 주소 또는 오래된 법인명을 언급하는 모든 셀, 도형 또는 하이퍼링크를 찾는 작업;
  • Template rendering — 워크북을 고객에게 보내기 전에 시트 전반에 걸쳐 {{PLACEHOLDER}} 토큰을 채우는 작업;
  • Link rot — 컴플라이언스 또는 보관 작업이 승인하기 전에 워크북에 포함된 URL이 여전히 유효한지 확인하는 작업;
  • Bulk correction — 수십 개의 시트에 걸쳐 오타나 잘못 표기된 열 값을 수정하거나, 특정 시트의 한 영역에만 적용하는 작업.

전통적인 옵션 — 자체 컴퓨터에서 실행되는 스크립팅 라이브러리, Excel 매크로, 또는 Windows 서버의 COM 구성 요소 — 모두 스프레드시트 로직을 직접 호스팅하고 확장해야 함을 의미합니다. Aspose.Cells Cloud는 이를 단순한 REST로 바꿉니다: 파일(또는 파일 이름만) 전송하고, 일치 항목 — 혹은 수정된 파일 — 을 반환받습니다.

이 게시물에서는 핵심 SearchController가 Aspose.Cells Cloud 마이크로서비스에서 제공하는 API를 살펴보고 (소스: 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] — stateless. 워크북을 요청 본문(multipart)으로 업로드하면 서버가 메모리에서 처리하고 클라우드 스토리지에 아무 것도 저장되지 않습니다. “파일에 무엇이 들어 있는지 알려줘”와 일회성 템플릿 작업에 적합합니다.
  • [CloudFileOperation] — storage-backed. 서버가 클라우드 스토리지에서 {name}을 가져오고(옵션으로 folder= 아래에 있을 수도 있음) 작업을 수행한 뒤, 교체 작업의 경우 결과를 바로 다시 기록합니다. 아무 것도 사용자의 컴퓨터로 전송되지 않습니다.

그 단 하나의 구분과 {worksheet} / {cellArea} 경로 세그먼트가 전체 정신 모델을 구성합니다. 이 게시물의 나머지는 단지 세부 사항일 뿐입니다.


2. 실제로 파싱하게 될 응답 모델

두 검색 패밀리는 작고 평평하며 바인딩하기 쉬운 형태를 반환합니다. Search는 **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"
    }
  ]
}

Broken-link 검색은 **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="Aspense.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도 동일하게 작동합니다(아래 참조). search/replace/broken-link 패밀리도 타입이 지정된 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(지역/로케일 설정)도 노출합니다 — 클라우드 스토리지 변형에서 storageName으로 볼 수 있는 동일한 선택적 매개변수입니다. .NET SDK는 regoin 철자를 유지하고; Python SDK는 동일한 두 설정을 password와 region이라고 부릅니다.

③ Python / Java

Python 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)

Java SDK는 setter를 통해 구축된 Request 객체와 동일한 형태를 따릅니다:

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"));

왜 하나가 아니라 세 개의 엔드포인트인가요? 라우트가 범위를 전달하기 때문입니다. 전체 워크북 엔드포인트는 이름과 쿼리를 받으며; 워크시트 엔드포인트는 워크시트 세그먼트를 받습니다; 범위 엔드포인트는 워크시트 및 범위 세그먼트를 받습니다. 이것은 깔끔하고 캐시 가능한 REST 구조이며 — “검색 범위 좁히기” 매개변수(worksheet, cellArea)는 로컬 파일 엔드포인트에 오직 존재한다는 의미입니다. 이는 한 범위에서 다른 범위로 호출을 포팅할 때 기억해 두면 좋습니다.

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가 채워집니다. 이것은 “grep the whole workbook” 기본 기능입니다.

7. 시나리오 D: 교체 — 그리고 두 가지 매우 다른 결과

Replace는 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. 시나리오 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 링크 주소와 표시 텍스트 모두 Hyperlink:Sheet1!B4
도형 worksheet.Shapes shape.Text — 텍스트 상자, 호출, 레이블 Shape:TextBox 3

그리고 여기에는 설계하기 이전에 알아두면 좋은 동작들이 있습니다:

문자열 셀만 검색됩니다. 스캔은 CellValueType.IsString을 기준으로 필터링합니다. 숫자, 날짜 또는 _불리언_을 포함하는 셀은 건너뛰어집니다 — 따라서 2025를 검색해도 해당 직렬값이 2025인 날짜 형식 셀과는 일치하지 않습니다. 수식이 텍스트로 평가되는 셀은 _일치_합니다, 왜냐하면 그 값 유형이 문자열이기 때문입니다.

대소문자 구분이 유일한 매칭 옵션입니다. ignoringCase는 InvariantCultureIgnoreCase와 InvariantCulture 비교 사이를 전환합니다 — 그 외는 없습니다. 생성된 API 문서가 암시하는 바와 달리 전체 단어, 정규식, 또는 “전체 셀 값 일치” 모드는 없습니다. 이러한 의미가 필요하다면 all-textitems 인벤토리를 가져와서 직접 필터링하십시오.

Replace는 단순하고 대소문자를 구분하는 리터럴 치환입니다. Search의 ignoringCase 플래그는 Replace에서는 동등한 것이 없습니다 — replace 경로에는 대소문자 무시 매개변수가 전혀 없습니다. 그리고 두 코드 경로는 내부적으로 다릅니다: 전체 워크시트 교체는 엔진의 Worksheet.Replace(...)에 위임하고, 범위 기반 교체는 범위를 반복하면서 각 문자열 셀을 cell.StringValue.Replace(...)로 다시 씁니다. 실용적인 결과: 범위 기반 교체는 문자열 셀만 영향을 미칩니다, 그리고 이는 패턴 기반이 아닌 리터럴 교체입니다.

하이퍼링크 일치는 주소를 보고, 캡션을 보고하지 않습니다. 검색이 하이퍼링크의 _표시 텍스트_와 일치하면, 반환되는 Content는 여전히 hyperlink.Address입니다. “여기서 찾음” 보고서를 렌더링하는 경우, URL을 기대하세요 — 캡션은 다시 반환되지 않습니다.

Broken-link 검사에서는 http://와 https://만 확인합니다. mailto: 링크, 로컬 파일 경로 및 내부 #Sheet1!A1 앵커는 완전히 건너뛰며 — 테스트되지 않으므로 결과에 나타나지 않습니다. 또한 셀뿐만 아니라 shapes에 연결된 하이퍼링크도 스캔합니다. 바로 그곳이 끊어진 링크가 숨겨지는 위치입니다. 주의할 점은 끊어진 링크 Position이 원시 hyperlink.Area에서 생성된다는 것입니다(Area.ToRangName()처럼 더 친숙한 형태가 아니라 검색 엔드포인트에서 사용됩니다). 따라서 두 패밀리가 위치를 동일하게 표시한다고 가정하지 마세요 — 안정적인 키가 필요하면 Worksheet + LinkAddress 쌍을 파싱하세요.

“Broken"는 “접근 불가"를 의미하며, “잘못된 상태 코드"를 의미하지 않습니다. 이 검사는 각 링크에 대해 HTTP HEAD 요청을 보내며 모든 응답 — 404 또는 500 포함 — 을 접근 가능으로 간주합니다; 요청이 throws(DNS 실패, 연결 거부, TLS 오류, 타임아웃)될 때만 링크를 끊어진 것으로 표시합니다. 따라서 출력은 “연락할 수 없는 링크” 로 간주하십시오. 실제로 필요로 하는 것이 “2xx를 반환하지 않는 링크"라면, 반환된 LinkAddress 값을 직접 다시 확인해야 합니다.

cellArea는 허용되지만 깨진 링크 엔드포인트에서는 적용되지 않습니다. BrokenLinks 구현은 워크시트 이름만으로 필터링합니다; 셀 영역 인자는 전달되지만 사용되지 않습니다. 실제로 이는 .../ranges/A1:F40/search/broken-links가 현재 동일 워크시트에 대해 /worksheet/search/broken-links와 동일하게 동작한다는 의미이며, 링크는 전체 시트에 대해 검증됩니다. 범위가 검사를 좁힌다고 가정하지 말고 _reports_를 해당 범위에 맞게 조정하거나(또는 반환된 목록을 위치별로 필터링) 하세요.

이 중 어느 것도 차단 요소는 아니며—이는 “데모에서 작동하는” 기능과 실제 운영 환경에서 예측 가능하게 동작하는 기능 사이의 차이점입니다.


10. 오류 처리 및 운영 메모

컨트롤러가 문서화하는 계약

상태 의미 일반적인 원인
400 잘못된 요청 잘못된 URL/매개변수 — 예: 잘못된 형식의 cellArea, 또는 누락된 searchText
401 인증되지 않음 인증에 실패했거나 유효한 자격 증명이 제공되지 않았습니다.
404 찾을 수 없음 소스 파일에 클라우드 저장소에서 접근할 수 없습니다.
500 서버 오류 스프레드시트 데이터를 가져오는 중 서비스에 이상이 발생했습니다.

내부적으로, 모든 작업은 헬퍼(WorkbookElementOperation, UpdateWorkbookElementOperation, UpdateWorkbookElementOperationAndSave)에 작업을 래핑하여 실패를 포착하고 이를 CellsApiException 작업 이름이 접두사로 붙은 형태로 다시 throw합니다 — 예를 들어 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를 사용하여 자동으로 인증합니다; raw cURL을 사용할 때는 먼저 /connect/token을 한 번 호출하십시오 (§4, ① 참조).

11. 검색 및 교체에 Aspose.Cells Cloud를 사용하는 이유는?

  • ✅ 제로 로컬 종속성 — Office/Excel 없이, COM 없이, 스크립팅 호스트 없이. 모든 언어, 모든 플랫폼(Linux, 컨테이너, 서버리스)에서 호출 가능;
  • ✅ 텍스트 검색보다 깊게 — 셀, 도형 및 하이퍼링크는 모두 일차적인 매치 대상이며, 실제 스프레드시트가 내용을 보관하는 바로 그 위치입니다;
  • ✅ 범위 지정 작업 — 워크북 / 워크시트 / 범위 단위로 작업하므로 50 MB 파일을 다시 쓰지 않고도 한 시트의 특정 영역을 수정할 수 있습니다;
  • ✅ 클라우드 네이티브 또는 무상태 — 스토리지에 이미 있는 파일은 절대 외부로 나가지 않으며; 로컬 업로드 작업은 전혀 지속되지 않습니다;
  • ✅ 고충실도 재작성 — 대체는 Aspose.Cells 엔진을 통해 적용되고 다시 직렬화되므로, 수식, 스타일, 차트 및 서식이 라운드 트립을 견뎌냅니다;
  • ✅ SDK 전반에 걸친 일관된 형태 — cURL, .NET, Python 및 Java 인터페이스가 1:1 매핑되므로, 한 언어에서 복사한 패턴이 다른 언어에서도 그대로 작동합니다.

지금 시작하세요: Aspose Cloud Dashboard에서 등록하고, 애플리케이션을 생성한 다음, 위의 스니펫 중 하나에 자격 증명을 넣고, 자신의 워크북 중 하나를 지정하세요 — 몇 분 안에 작동하는 콘텐츠 감사를 받을 수 있습니다.

이 내용이 도움이 되었나요? 별표를 달거나, 북마크하거나, 공유해 보세요 — 그리고 댓글에 워크북 검색 및 교체를 어떻게 사용하고 있는지 알려주세요.