รับคุณสมบัติแบบ Effective ของ Shape จากการนำเสนอใน C++

ทำความเข้าใจ Local, Inherited และ Effective Properties

การจัดรูปแบบ PowerPoint สามารถมาจากหลายแหล่ง ค่าเก็บโดยตรงบนอ็อบเจ็กต์คือ ค่า local ถ้าค่านั้นไม่ได้ตั้งค่า PowerPoint จะมองที่แหล่งข้อมูลแบบพาเรนต์ เช่น ค่าตั้งต้นของย่อหน้า, สไตล์ข้อความ, เมนูหรือสไลด์แม่, ธีม หรือค่าตั้งต้นระดับการนำเสนอ ค่าต่าง ๆ เหล่านี้คือ ค่า inherited ค่าที่เหลือหลังจากที่ลำดับชั้นทั้งหมดได้รับการแก้ไขคือ ค่า effective — ค่าที่ใช้ในการเรนเดอร์อ็อบเจ็กต์

ตัวอย่างเช่น ส่วนของข้อความอาจไม่ได้กำหนดความสูงของฟอนต์ของตนเอง ความสูงของฟอนต์ local ของมันจึงเป็น std::numeric_limits<float>::quiet_NaN() ซึ่งหมายถึง “ไม่ได้ตั้งค่าให้ที่นี่” ส่วนของข้อความสามารถสืบทอดความสูงจากย่อหน้า, สไตล์ข้อความตั้งต้นของการนำเสนอ หรือแหล่งที่สามารถใช้งานได้อื่น ๆ การเรียก GetEffective บนรูปแบบส่วนจะคืนค่าความสูงที่ถูกแก้ไขแล้ว

ใช้ข้อมูลการจัดรูปแบบสองแบบเพื่อวัตถุประสงค์ที่ต่างกัน:

  • อ่านหรือเปลี่ยนอ็อบเจ็กต์รูปแบบ local เช่น IPortionFormat เมื่อคุณต้องการควบคุมว่าค่าถูกกำหนดที่ระดับใด
  • อ่านอ็อบเจ็กต์ข้อมูล effective เช่น IPortionFormatEffectiveData เมื่อคุณต้องการผลลัพธ์ที่ได้หลังการเรนเดอร์ ข้อมูล effective เป็นแบบอ่าน‑เท่านั้น

เปรียบเทียบ Local, Inherited และ Effective Values

ตัวอย่างเต็มต่อไปนี้สร้างรูปทรงและกำหนดความสูงของฟอนต์ในระดับการนำเสนอ, ย่อหน้าและส่วนของข้อความแต่ละระดับ แต่ละขั้นตอนจะพิมพ์ค่าที่กำหนดในระดับเหล่านั้นและค่า effective ที่ได้จากส่วนข้อความเดียวกัน ตัวอย่างยังแสดงว่าทำไมต้องอ่านข้อมูล effective อีกครั้งหลังจากมีการเปลี่ยนแปลงการจัดรูปแบบ

#include <DOM/IAutoShape.h>
#include <DOM/IParagraph.h>
#include <DOM/IParagraphFormat.h>
#include <DOM/IPortion.h>
#include <DOM/IPortionFormat.h>
#include <DOM/IPortionFormatEffectiveData.h>
#include <DOM/IShapeCollection.h>
#include <DOM/ISlide.h>
#include <DOM/ITextFrame.h>
#include <DOM/ITextStyle.h>
#include <DOM/Presentation.h>
#include <DOM/ShapeType.h>
#include <Export/SaveFormat.h>
#include <system/console.h>
#include <system/object_ext.h>
#include <system/string.h>
#include <cmath>
#include <limits>

using namespace Aspose::Slides;
using namespace Aspose::Slides::Export;
using namespace System;

auto presentation = System::MakeObject<Presentation>();

auto slide = presentation->get_Slide(0);
auto shape = slide->get_Shapes()->AddAutoShape(ShapeType::Rectangle, 100.0f, 100.0f, 500.0f, 80.0f, false);
auto textFrame = shape->AddTextFrame(u"Effective formatting");
auto paragraph = textFrame->get_Paragraph(0);
auto portion = paragraph->get_Portion(0);

// กำหนดค่าที่สืบทอดในสองระดับที่แตกต่างกัน.
presentation->get_DefaultTextStyle()->GetLevel(0)->get_DefaultPortionFormat()->set_FontHeight(20.0f);
paragraph->get_ParagraphFormat()->get_DefaultPortionFormat()->set_FontHeight(28.0f);

auto formatLocalValue = [](float value) -> System::String
{
    return std::isnan(value) ? System::String(u"<not set>") : System::ObjectExt::ToString(value);
};

auto printFontHeights = [&](System::String caption)
{
    auto presentationValue = presentation->get_DefaultTextStyle()->GetLevel(0)->get_DefaultPortionFormat()->get_FontHeight();
    auto paragraphValue = paragraph->get_ParagraphFormat()->get_DefaultPortionFormat()->get_FontHeight();
    auto localValue = portion->get_PortionFormat()->get_FontHeight();

    // อ่านข้อมูล effective หลังจากการเปลี่ยนแปลงก่อนหน้า.
    auto effectiveValue = portion->get_PortionFormat()->GetEffective()->get_FontHeight();

    System::Console::WriteLine(caption);
    System::Console::WriteLine(System::String(u"  Presentation default: ") + formatLocalValue(presentationValue));
    System::Console::WriteLine(System::String(u"  Paragraph default:    ") + formatLocalValue(paragraphValue));
    System::Console::WriteLine(System::String(u"  Portion local:        ") + formatLocalValue(localValue));
    System::Console::WriteLine(System::String(u"  Portion effective:    ") + effectiveValue);
};

printFontHeights(u"The portion inherits from the paragraph");

// ค่าท้องถิ่นบนส่วนจะครอบคลุมค่าที่สืบทอดทั้งสองค่า.
portion->get_PortionFormat()->set_FontHeight(36.0f);
printFontHeights(u"A local value overrides inherited values");

// การเปลี่ยนค่าที่สืบทอดจะไม่ทับค่าท้องถิ่นที่มีอยู่.
paragraph->get_ParagraphFormat()->get_DefaultPortionFormat()->set_FontHeight(30.0f);
printFontHeights(u"The local value still has priority");

// ลบค่าท้องถิ่นออก ตอนนี้ส่วนจะสืบทอดจากย่อหน้าอีกครั้ง.
portion->get_PortionFormat()->set_FontHeight(std::numeric_limits<float>::quiet_NaN());
printFontHeights(u"The local value is cleared");

// ลบค่าของย่อหน้าออก ค่าตั้งต้นของการนำเสนอจะเป็นผลลัพธ์ตอนนี้.
paragraph->get_ParagraphFormat()->get_DefaultPortionFormat()->set_FontHeight(std::numeric_limits<float>::quiet_NaN());
printFontHeights(u"The paragraph value is cleared");

presentation->Save(u"effective-properties.pptx", SaveFormat::Pptx);
presentation->Dispose();

ลำดับความสำคัญในตัวอย่างนี้คือการจัดรูปแบบ local ของส่วน, ตามด้วยการจัดรูปแบบของย่อหน้า, แล้วจึงเป็นค่าตั้งต้นของการนำเสนอ วัตถุอื่น ๆ อาจมีห่วงโซ่การสืบทอดที่แตกต่างกัน แต่หลักการคงเดิม: ค่าที่ระบุอย่างเฉพาะเจาะจะแซงค่าที่สืบทอด และ GetEffective จะคืนค่าผลลัพธ์สุดท้าย

รับคุณสมบัติของข้อความแบบ Effective

การจัดรูปแบบข้อความถูกแยกออกเป็นหลายอ็อบเจ็กต์:

  • ITextFrameFormat::GetEffective แก้ไขคุณสมบัติของเฟรมข้อความ เช่น ระยะขอบ, การยึด, autofit, และทิศทางข้อความแนวตั้ง
  • ITextStyle::GetEffective แก้ไขการจัดรูปแบบย่อหน้าสำหรับแต่ละระดับของสไตล์ข้อความ
  • IParagraphFormat::GetEffective แก้ไขคุณสมบัติของย่อหน้า เช่น การจัดแนว, การเยื้อง, และรายการสัญลักษณ์
  • IPortionFormat::GetEffective แก้ไขคุณสมบัติอักขระ เช่น ความสูงของฟอนต์, แบบอักษร, สี, ตัวหนาและตัวเอียง

สำหรับตัวอย่างต่อไป, ไฟล์ text-formatting.pptx ต้องมีอย่างน้อยหนึ่งสไลด์และหนึ่ง IAutoShape ที่มีกรอบข้อความไม่ว่างเปล่า IAutoShape สามารถปรากฏได้ตำแหน่งใดก็ได้ในคอลเลกชันของรูปทรง; โค้ดจะค้นหาอ็อบเจ็กต์ที่เหมาะสมและตรวจสอบก่อนใช้งาน

#include <DOM/IAutoShape.h>
#include <DOM/IParagraph.h>
#include <DOM/IParagraphCollection.h>
#include <DOM/IParagraphFormat.h>
#include <DOM/IPortion.h>
#include <DOM/IPortionCollection.h>
#include <DOM/IPortionFormat.h>
#include <DOM/IShapeCollection.h>
#include <DOM/ISlide.h>
#include <DOM/ITextFrame.h>
#include <DOM/ITextFrameFormat.h>
#include <DOM/ITextStyle.h>
#include <DOM/Presentation.h>
#include <system/console.h>
#include <system/exceptions.h>
#include <system/object_ext.h>
#include <system/shared_ptr.h>

using namespace Aspose::Slides;
using namespace System;

auto presentation = System::MakeObject<Presentation>(u"text-formatting.pptx");

if (presentation->get_Slides()->get_Count() == 0)
    throw System::InvalidOperationException(u"The presentation contains no slides.");

auto slide = presentation->get_Slide(0);
System::SharedPtr<IAutoShape> shape;

for (int shapeIndex = 0; shapeIndex < slide->get_Shapes()->get_Count(); ++shapeIndex)
{
    auto candidate = slide->get_Shapes()->idx_get(shapeIndex);

    if (!System::ObjectExt::Is<IAutoShape>(candidate))
        continue;

    auto autoShape = System::ExplicitCast<IAutoShape>(candidate);
    auto candidateTextFrame = autoShape->get_TextFrame();

    if (candidateTextFrame == nullptr || candidateTextFrame->get_Paragraphs()->get_Count() == 0)
        continue;

    if (candidateTextFrame->get_Paragraph(0)->get_Portions()->get_Count() == 0)
        continue;

    shape = autoShape;
    break;
}

if (shape == nullptr)
    throw System::InvalidOperationException(u"The first slide must contain an IAutoShape with non-empty text.");

auto textFrame = shape->get_TextFrame();
auto paragraph = textFrame->get_Paragraph(0);
auto portion = paragraph->get_Portion(0);

auto textFrameEffective = textFrame->get_TextFrameFormat()->GetEffective();
auto paragraphEffective = paragraph->get_ParagraphFormat()->GetEffective();
auto portionEffective = portion->get_PortionFormat()->GetEffective();

System::Console::WriteLine(u"Text frame margins:");
System::Console::WriteLine(System::String(u"  Left: ") + textFrameEffective->get_MarginLeft());
System::Console::WriteLine(System::String(u"  Top: ") + textFrameEffective->get_MarginTop());
System::Console::WriteLine(System::String(u"  Right: ") + textFrameEffective->get_MarginRight());
System::Console::WriteLine(System::String(u"  Bottom: ") + textFrameEffective->get_MarginBottom());
System::Console::WriteLine(System::String(u"Paragraph alignment: ") + System::ObjectExt::ToString(paragraphEffective->get_Alignment()));
System::Console::WriteLine(System::String(u"Font height: ") + portionEffective->get_FontHeight());
System::Console::WriteLine(System::String(u"Bold: ") + System::ObjectExt::ToString(portionEffective->get_FontBold()));

auto effectiveTextStyle = textFrame->get_TextFrameFormat()->get_TextStyle()->GetEffective();
for (int level = 0; level < 9; ++level)
{
    auto levelEffective = effectiveTextStyle->GetLevel(level);
    System::Console::WriteLine(System::String(u"Level ") + level + u" indent: " + levelEffective->get_Indent());
}

presentation->Dispose();

รับคุณสมบัติ 3D แบบ Effective

IThreeDFormat::GetEffective คืนค่าอ็อบเจ็กต์ IThreeDFormatEffectiveData หนึ่งตัวที่จัดกลุ่มการตั้งค่า 3D ทั้งหมดที่แก้ไขแล้ว ข้อมูล camera, light rig, top bevel และ bottom bevel จะเปิดเผยการตั้งค่า effective ที่สอดคล้องกัน การอ่านการตั้งค่าเหล่านี้ร่วมกันทำให้เข้าใจรูปลักษณ์ 3D สุดท้ายของรูปทรงได้ง่ายขึ้น

สำหรับตัวอย่างนี้, ไฟล์ shape-3d.pptx ต้องมีอย่างน้อยหนึ่งรูปทรงบนสไลด์แรก หากคุณต้องการให้ผลลัพธ์มีค่าที่ไม่ใช่ค่าเริ่มต้น ให้กำหนดกล้อง 3D, การจัดแสง หรือการตั้งค่า bevel ให้กับรูปทรงนั้น

#include <DOM/ICameraEffectiveData.h>
#include <DOM/ILightRigEffectiveData.h>
#include <DOM/IShape.h>
#include <DOM/IShapeBevelEffectiveData.h>
#include <DOM/IShapeCollection.h>
#include <DOM/ISlide.h>
#include <DOM/IThreeDFormat.h>
#include <DOM/IThreeDFormatEffectiveData.h>
#include <DOM/Presentation.h>
#include <system/console.h>
#include <system/exceptions.h>
#include <system/object_ext.h>

using namespace Aspose::Slides;
using namespace System;

auto presentation = System::MakeObject<Presentation>(u"shape-3d.pptx");

if (presentation->get_Slides()->get_Count() == 0 || presentation->get_Slide(0)->get_Shapes()->get_Count() == 0)
    throw System::InvalidOperationException(u"The first slide must contain a shape.");

auto shape = presentation->get_Slide(0)->get_Shape(0);
auto threeDEffective = shape->get_ThreeDFormat()->GetEffective();

System::Console::WriteLine(u"Camera:");
System::Console::WriteLine(System::String(u"  Type: ") + System::ObjectExt::ToString(threeDEffective->get_Camera()->get_CameraType()));
System::Console::WriteLine(System::String(u"  Field of view: ") + threeDEffective->get_Camera()->get_FieldOfViewAngle());
System::Console::WriteLine(System::String(u"  Zoom: ") + threeDEffective->get_Camera()->get_Zoom());

System::Console::WriteLine(u"Light rig:");
System::Console::WriteLine(System::String(u"  Type: ") + System::ObjectExt::ToString(threeDEffective->get_LightRig()->get_LightType()));
System::Console::WriteLine(System::String(u"  Direction: ") + System::ObjectExt::ToString(threeDEffective->get_LightRig()->get_Direction()));

System::Console::WriteLine(u"Top bevel:");
System::Console::WriteLine(System::String(u"  Type: ") + System::ObjectExt::ToString(threeDEffective->get_BevelTop()->get_BevelType()));
System::Console::WriteLine(System::String(u"  Width: ") + threeDEffective->get_BevelTop()->get_Width());
System::Console::WriteLine(System::String(u"  Height: ") + threeDEffective->get_BevelTop()->get_Height());

presentation->Dispose();

รับการจัดรูปแบบตารางแบบ Effective

การจัดรูปแบบตารางสามารถมาจากสไตล์ตารางและจากฟอร์แมตที่ใช้กับตารางทั้งหมด, คอลัมน์, แถว หรือเซลล์เฉพาะ ในกรณีที่มีการขัดแย้งระหว่างการกำหนด fill อย่างชัดเจน ลำดับความสำคัญคือ เซลล์, แถว, คอลัมน์, แล้วจึงเป็นตารางทั้งหมด ฟอร์แมต effective ของเซลล์คือฟอร์แมตสุดท้ายที่ใช้ในการวาดเซลล์นั้น

สำหรับตัวอย่างนี้, ไฟล์ table-formatting.pptx ต้องมีอย่างน้อยหนึ่งตารางบนสไลด์แรก ตารางต้องมีอย่างน้อยหนึ่งแถวและหนึ่งคอลัมน์ โค้ดจะค้นหา ITable แทนการสันนิษฐานว่ารูปทรงแรกเป็นตาราง

#include <DOM/IFillFormatEffectiveData.h>
#include <DOM/IShapeCollection.h>
#include <DOM/ISlide.h>
#include <DOM/Presentation.h>
#include <DOM/Table/ICell.h>
#include <DOM/Table/ICellFormat.h>
#include <DOM/Table/IColumn.h>
#include <DOM/Table/IColumnCollection.h>
#include <DOM/Table/IColumnFormat.h>
#include <DOM/Table/IRow.h>
#include <DOM/Table/IRowCollection.h>
#include <DOM/Table/IRowFormat.h>
#include <DOM/Table/ITable.h>
#include <DOM/Table/ITableFormat.h>
#include <system/console.h>
#include <system/exceptions.h>
#include <system/object_ext.h>
#include <system/shared_ptr.h>

using namespace Aspose::Slides;
using namespace System;

auto presentation = System::MakeObject<Presentation>(u"table-formatting.pptx");

if (presentation->get_Slides()->get_Count() == 0)
    throw System::InvalidOperationException(u"The presentation contains no slides.");

auto slide = presentation->get_Slide(0);
System::SharedPtr<ITable> table;

for (int shapeIndex = 0; shapeIndex < slide->get_Shapes()->get_Count(); ++shapeIndex)
{
    auto candidate = slide->get_Shapes()->idx_get(shapeIndex);

    if (System::ObjectExt::Is<ITable>(candidate))
    {
        table = System::ExplicitCast<ITable>(candidate);
        break;
    }
}

if (table == nullptr)
    throw System::InvalidOperationException(u"The first slide must contain a table.");

if (table->get_Rows()->get_Count() == 0 || table->get_Columns()->get_Count() == 0)
    throw System::InvalidOperationException(u"The table must contain at least one cell.");

auto tableEffective = table->get_TableFormat()->GetEffective();
auto rowEffective = table->get_Row(0)->get_RowFormat()->GetEffective();
auto columnEffective = table->get_Column(0)->get_ColumnFormat()->GetEffective();
auto cellEffective = table->idx_get(0, 0)->get_CellFormat()->GetEffective();

System::Console::WriteLine(System::String(u"Table fill: ") + System::ObjectExt::ToString(tableEffective->get_FillFormat()->get_FillType()));
System::Console::WriteLine(System::String(u"Row fill: ") + System::ObjectExt::ToString(rowEffective->get_FillFormat()->get_FillType()));
System::Console::WriteLine(System::String(u"Column fill: ") + System::ObjectExt::ToString(columnEffective->get_FillFormat()->get_FillType()));
System::Console::WriteLine(System::String(u"Final cell fill: ") + System::ObjectExt::ToString(cellEffective->get_FillFormat()->get_FillType()));

presentation->Dispose();

หากคุณต้องการสีแทนที่จะเป็นประเภท fill อย่างเดียว ให้ตรวจสอบ FillType ที่ effective ก่อน แล้วจึงอ่านคุณสมบัติที่สอดคล้องกับประเภทนั้น — ตัวอย่างเช่น SolidFillColor สำหรับ fill แบบทึบ

อ่าน Effective Data อีกครั้งหลังการเปลี่ยนแปลง

Effective data อธิบายลำดับชั้นการจัดรูปแบบในขณะที่ได้รับการแก้ไข เรียก GetEffective อีกครั้งหลังจากเปลี่ยนแปลงสิ่งใดที่อาจมีส่วนร่วมในลำดับชั้นนั้น รวมถึง:

  • การจัดรูปแบบ local ของอ็อบเจ็กต์;
  • ค่าตั้งต้นของย่อหน้า หรือเฟรมข้อความ;
  • สไตล์ตาราง, ตาราง, คอลัมน์, แถว หรือฟอร์แมตของเซลล์;
  • การจัดรูปแบบของเลย์เอาต์หรือสไลด์แม่;
  • ข้อมูลธีมหรือค่าตั้งต้นระดับการนำเสนอ;
  • เลย์เอาต์หรือสไลด์แม่ที่กำหนดให้กับสไลด์

อย่าเก็บอ็อบเจ็กต์ effective data เป็นสแนปชอตถาวร Aspose.Slides อาจแคชบางส่วนของ effective data ภายในและการเรียก GetEffective ครั้งต่อมาจะรีเฟรชข้อมูลนั้น หากคุณต้องการเปรียบเทียบค่าก่อนและหลังการเปลี่ยนแปลง ให้คัดลอกค่าขนาดสเกลาร์ที่ต้องการ — เช่น ความสูงของฟอนต์, สี, การจัดแนว หรือความกว้างของ bevel — ไปยังตัวแปรของคุณก่อนทำการเปลี่ยนแปลง

เพื่อเปลี่ยนค่า ให้ปรับอ็อบเจ็กต์รูปแบบ local ที่เหมาะสมแล้วเรียก GetEffective เพื่อตรวจสอบผลลัพธ์ อ็อบเจ็กต์ effective data เองเป็นแบบอ่าน‑เท่านั้น

FAQ

ฉันจะทราบได้ว่าระดับใดให้ค่าที่ effective?

Effective data มีค่าที่สุดท้าย ไม่ได้บอกแหล่งที่มาของค่า ตรวจสอบอ็อบเจ็กต์ local ที่เกี่ยวข้องจากระดับที่เจาะจงที่สุดแล้วค่อยขยายออกไป สำหรับข้อความอาจรวมถึงส่วน, ย่อหน้า, เฟรมข้อความ, เลย์เอาต์, สไลด์แม่, ธีม และค่าตั้งต้นของการนำเสนอ ค่าที่ไม่ได้กำหนดเช่น std::numeric_limits<float>::quiet_NaN() หรือ nullptr แสดงว่าการค้นหายังดำเนินต่อไปที่ระดับอื่น

จะเกิดอะไรขึ้นเมื่อไม่มีระดับใดกำหนดคุณสมบัตินั้น?

Aspose.Slides จะแก้ไขเป็นค่าเริ่มต้นของ PowerPoint หรือของไลบรารี ค่าที่แก้ไขแล้วจะปรากฏใน effective data แม้ว่าจะไม่มีอ็อบเจ็กต์ local ใดกำหนดค่าโดยตรง

ทำไมค่าที่ effective บางครั้งจึงเท่ากับค่าที่ local?

ค่าที่ local ชนะการคำนวณการสืบทอด ซึ่งเป็นที่คาดหวังเมื่อคุณสมบัติถูกตั้งค่าโดยเจาะจงบนอ็อบเจ็กต์และไม่มีกฎที่เฉพาะเจาะจงกว่าสามารถทับได้

ควรใช้ข้อมูล local แทนข้อมูล effective เมื่อใด?

ใช้ข้อมูล local เพื่อตรวจสอบหรือแก้ไขระดับการจัดรูปแบบเฉพาะ ใช้ข้อมูล effective เมื่อคุณต้องการลักษณะที่แสดงผลขั้นสุดท้ายหลังจากการสืบทอด, กฎของธีม, และสไตล์ที่เกี่ยวข้องทั้งหมดได้ถูกแก้ไขแล้ว ตัวอย่าง การเปรียบเทียบเต็ม (#compare-local-inherited-and-effective-values) แสดงการใช้ทั้งสองแบบในกระบวนการเดียวกัน