نحوه ساخت کنترل مجموعه داده PCF با استفاده از REACT

Summarize this content to 400 words in Persian Lang
در این آموزش، شما یک کنترل داده تعاملی PCF را با استفاده از React ایجاد میکنید که میتواند در شبکه موجودیت Dynamics CRM ادغام شود.
تکنیک هایی که در این آموزش خواهید آموخت به شما درک عمیق تری از کنترل های PCF در Dynamics CRM می دهد. در سراسر این راهنما، ما همه چیز را از راهاندازی محیط توسعه تا استقرار و آزمایش کنترل سفارشی شما پوشش خواهیم داد.
چی میسازی؟
در این آموزش، کنترلی خواهید ساخت که فایل اکسل پیوست شده به یادداشتهای درون CRM را نمایش میدهد و به کاربران روشی بصریتر و سازماندهیشدهتر برای دسترسی به پیوستهای اکسل مرتبط با رکوردهای یادداشت ارائه میدهد.
در اینجا میتوانید ببینید که وقتی کارتان تمام شد چگونه به نظر میرسد:
در برگه Timeline، سه یادداشت مرتبط با حساب وجود دارد که هر کدام یک فایل اکسل پیوست شده است.
در تب Notes، کنترل سفارشی ما اضافه شده است که این فایلهای اکسل را استخراج کرده و در منوی انتخاب فایل فهرست میکند و با انتخاب فایل، برگههای آن فایل اکسل در منوی انتخاب برگه نمایش داده میشود.
وقتی کاربر برگهای را انتخاب میکند، دادههای آن مطابق شکل بالا در شبکه نمایش داده میشود، و همانطور که متوجه شدید ما یک قابلیت دانلود سفارشی نیز ایجاد میکنیم که فایل انتخابی را در سیستم ما دانلود میکند.
راه اندازی برای آموزش
قبل از شروع ساختن کنترلهای PCF با React، مطمئن شوید که ابزارهای لازم را روی دستگاه خود نصب کردهاید:
Node.js: نسخه LTS توصیه می شود
کد ویژوال استودیو (VS Code): برای تجربه بهتر کدنویسی توصیه می شود از ویرایشگری مانند Visual Studio Code استفاده کنید.
Microsoft Power Platform CLI: برای نصب Power Platform CLI از ابزارهای Power Platform برای VS Code یا Power Platform CLI برای ویندوز استفاده کنید.
ایجاد یک پروژه جدید
هنگامی که محیط شما آماده شد، یک پروژه کنترل مجموعه داده PCF جدید ایجاد کنید.
کد ویژوال استودیو را باز کنید و از ترمینال به پوشه ای که می خواهید پروژه کنترل PCF را در آن ایجاد کنید بروید.
دستور زیر را از ترمینال خود برای ایجاد یک پروژه کنترل PCF جدید اجرا کنید:
pac pcf init –namespace SampleNamespace –name ReactDatasetControl –template dataset –framework react –run-npm-install
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
–namespace فضای نام را برای کنترل شما مشخص می کند.
–name نام کنترل شما را مشخص می کند.
–template نوع کنترل را مشخص می کند (مثلاً فیلد یا مجموعه داده)
–framework (اختیاری) چارچوب کنترل را مشخص می کند.
–run-npm-install ماژول های گره مورد نیاز را برای کنترل نصب می کند.
اجرای موارد بالا pac pcf init فرمان یک کنترل PCF اولیه را با تمام فایلها و وابستگیهای مورد نیاز تنظیم میکند و آن را برای سفارشیسازی و استقرار در PowerApps آماده میکند.
در این آموزش ما از کتابخانه XLSX برای کار با فایل های اکسل استفاده می کنیم. آنها را در پروژه خود با استفاده از
npm install xlsx
npm install –save-dev ajv
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
نمای کلی
اکنون که راه اندازی شده اید، بیایید مروری بر PCF Dataset Control داشته باشیم!
بررسی کد شروع
در کاوشگر سه بخش اصلی را مشاهده خواهید کرد:
node_modules شامل تمام بسته های گره مورد نیاز برای پروژه است.
ReactDatasetControl پوشه پروژه حاوی فایل های اصلی است.
eslintrc.json ،package.json فایل های پیکربندی پروژه هستند.
بیایید نگاهی به برخی از فایل های کلیدی بیندازیم.
ControlManifest.Input.xml
اینجا جایی است که پیکربندی و ویژگی های کنترل PCF خود را تعریف می کنید. این شامل اطلاعاتی مانند نام کنترل، نسخه، توضیحات و انواع داده هایی است که می پذیرد.
index.ts
این به عنوان نقطه ورود برای منطق تجاری کنترل PCF شما عمل می کند. جایی است که شما رفتار و تعاملات کنترل خود را تعریف می کنید.
روش های چرخه زندگی:
init: این متد زمانی فراخوانی می شود که کنترل مقداردهی اولیه شود. برای راهاندازی کنترل، از جمله کنترلکنندههای رویداد، و رندر کردن رابط کاربری اولیه استفاده میشود.
updateView: هر زمان که کنترل نیاز به به روز رسانی داشته باشد، این روش فراخوانی می شود، برای مثال زمانی که داده ها یا ویژگی های کنترل تغییر می کند. برای رندر مجدد رابط کاربری با آخرین داده ها استفاده می شود.
getOutputs: این متد مقدار فعلی خروجی های کنترل را برمی گرداند که می تواند توسط اجزای دیگر استفاده شود یا در پایگاه داده ذخیره شود.
destroy: این متد زمانی فراخوانی می شود که کنترل از DOM حذف شود. برای پاکسازی منابع، مانند کنترل کننده رویدادها، برای جلوگیری از نشت حافظه استفاده می شود.
در کنترل ما، updateView متد زمانی فراخوانی می شود که صفحه بارگیری می شود. این روش رندر می کند HelloWorld جزء از HelloWorld.tsx فایل
ساخت جزء
بیایید با ایجاد یک فایل App.tsx در داخل پوشه پروژه ReactDatasetControl شروع کنیم. این منطق کنترل PCF ما را تشکیل می دهد.
/* App.tsx */
import * as React from ‘react’;
import { IInputs } from “./generated/ManifestTypes”;
import { DetailsList } from ‘@fluentui/react’;
export function PCFControl({sampleDataSet} : IInputs) {
const records = [
{
“First Name”: “Saturo”,
“Last Name”: “Gojo”,
“Domain”: “Infinity Void”
},
{
“First Name”: “Sukuna”,
“Last Name”: “Ryomen”,
“Domain”: “Malevolent Shrine”
}
];
return DetailsList items={records}/>
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
خطوط 1-3 تمام واردات لازم برای کنترل را به ارمغان می آورد.
خط بعدی تابعی به نام تعریف می کند PCFControl . را export کلیدواژه جاوا اسکریپت این تابع را خارج از این فایل قابل دسترسی می کند.
در PCFControl تابع a sampleDataSet ویژگی ارسال می شود که شامل داده ها/سوابق شبکه ای است که کنترل ما به آنها متصل می شود.
تابع a را برمی گرداند DetailsList کنترل با سوابق داده های ارسال شده به آن items دارایی
DetailsList یک کنترل واکنش Fluent UI ایجاد شده توسط مایکروسافت است که برای مشاهده داده ها در قالب لیست استفاده می شود.
index.ts
فایل با عنوان را باز کنید index.ts ، ما را وارد کنید PCFControl در بالای فایل و اجازه دهید تغییر دهید updateView تابعی برای برگرداندن کنترل سفارشی ما.
import { PCFControl } from “./App”
// …
public updateView(context: ComponentFramework.ContextIInputs>): React.ReactElement
{
const props: IInputs = { sampleDataSet: context.parameters.sampleDataSet };
return React.createElement(PCFControl, props);
}
// …
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
context.parameters.sampleDataSet به ویژگی مجموعه داده از context پارامتر این شامل داده ها/سوابق شبکه ای است که کنترل ما در بخش های بعدی به آن ملزم خواهد شد. سپس یک عنصر React متشکل از PCFControl مؤلفه و مجموعه داده ارسالی props به عنوان خواص به آن.
اکنون که یک ساختار اساسی برای کنترل خود ایجاد کرده ایم، بیایید کنترل خود را بسازیم و اجرا کنیم تا ببینیم ظاهر آن چگونه است. برای مشاهده کنترل در مرورگر محلی خود دستورات زیر را در ترمینال اجرا کنید.
npm run build
npm start watch
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
اکنون می توانید رکوردهای خود را در قالب لیست جدولی مشاهده کنید،
استفاده از داده ها از طریق props
در مرحله بعدی، میخواهیم دادههای شبکه CRM را که از آن دریافت میکنیم، نمایش دهیم sampleDataSet ویژگی در کنترل به جای استفاده از رکوردهای داده استاتیک.
باز کنید App.tsx و اجازه دهید ابتدا یک تابع به نام ایجاد کنیم parseDatasetToJSON در داخل تابع PCFControl، که آن را تجزیه می کند sampleDataSet ویژگی (شامل داده های شبکه) و آن داده ها را در آرایه ای از اشیاء json برمی گرداند.
// …
function parseDatasetToJSON()
{
const jsonData = [];
for(const recordID of sampleDataSet.sortedRecordIds)
{
// Dataset record
const record = sampleDataSet.records[recordID];
const temp: Recordstring, any> = {};
// Loop through each dataset columns
for(const column of sampleDataSet.columns)
{
temp[column.name] = record.getFormattedValue(column.name)
}
jsonData.push(temp);
}
return jsonData;
}
// …
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
اکنون که تابعی برای تبدیل مجموعه داده به JSON دریافت کردهایم، میخواهیم این تابع را بهسرعت فراخوانی کنیم sampleDataSet دارایی بارگیری یا تغییر کرده است.
React یک توابع ویژه به نام ارائه می کند قلاب، مانند useState که به شما این امکان را می دهد که داده های خود را در یک متغیر ویژگی نوع حالت و useEffect به شما امکان می دهد توابع مربوط به هر یک از تغییر ویژگی نوع حالت را فراخوانی کنید.
بیشتر بدانید useState و useEffect از،
واردات useState و useEffect در بالای فایل، سپس یک متغیر حالت به نام را مقداردهی اولیه کنید notes که رکوردهای مجموعه داده با فرمت JSON ما را ذخیره می کند.
زمانی که sampleDataSet دارایی بارگیری/تغییر شده است، useEffect تابع فراخوانی می شود و notes متغیر با رکوردهای مجموعه داده جدید به روز می شود.
سپس DetailsList را به روز می کنیم items دارایی برای استفاده notes داده ها به جای سوابق داده های ایستا.
import { useState, useEffect } from ‘react’;
// …
const [notes, setNotes] = useStateArrayRecordstring, any>>>([]); // Array of JSON Objects
useEffect(() => {
const notesRecords = parseDatasetToJSON();
setNotes(notesRecords);
}, [sampleDataSet]); // On dataset property load or change
return DetailsList items={notes}/>
// …
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
در این مرحله شما App.tsx کد باید چیزی شبیه به این باشد:
import * as React from ‘react’;
import { useState, useEffect } from ‘react’;
import { IInputs } from “./generated/ManifestTypes”;
import { DetailsList } from ‘@fluentui/react’;
export function PCFControl({sampleDataSet} : IInputs) {
function parseDatasetToJSON()
{
const jsonData = [];
for(const recordID of sampleDataSet.sortedRecordIds)
{
// Dataset record
const record = sampleDataSet.records[recordID];
const temp: Recordstring, any> = {};
// Loop through each dataset columns
for(const column of sampleDataSet.columns)
{
temp[column.name] = record.getFormattedValue(column.name)
}
jsonData.push(temp);
}
return jsonData;
}
const [notes, setNotes] = useStateArrayRecordstring, any>>>([]); // Array of JSON Objects
useEffect(() => {
const notesRecords = parseDatasetToJSON();
setNotes(notesRecords);
}, [sampleDataSet]); // On dataset property load or change
return DetailsList items={notes}/>
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
اکنون پروژه خود را بسازید، و باید چیزی شبیه به این را ببینید،
در بارگذاری، کنترل مجموعه داده PCF این مجموعه داده ساختگی را فراهم می کند. برای ارائه مجموعه داده های سفارشی خود، از قسمت هایلایت شده پایین سمت راست، هر فایل اکسلی را که حاوی لیستی از ستون ها و ردیف ها باشد، انتخاب کنید. در انتخاب PCF Dataset Control این فایل اکسل را به sampleDataSet دارایی
درک موجودیت CRM: یادداشت ها
در این آموزش ما در حال ایجاد یک کنترل مجموعه داده PCF برای استفاده در موجودیت OOB Notes Dynamics CRM هستیم. بیایید یک لحظه کوتاه به مرور برخی از ستونهای کلیدی موجودیت Notes که بعداً در کنترل ما استفاده خواهند شد، اختصاص دهیم.
را یادداشت ها موجودیت در Dynamics CRM برای ذخیره و مدیریت پیوستها یا نظرات مرتبط با سایر نهادها، مانند حسابها، مخاطبین یا فرصتها استفاده میشود. اغلب برای پیگیری پرونده ها یا یادداشت های مهم مربوط به سوابق استفاده می شود.
در اینجا یک نمای کلی از ستونهای کلیدی موجودیت Notes آورده شده است:
نام فایل (filename): این ستون نام فایل پیوست شده به یادداشت را ذخیره می کند. این یک فیلد رشته ای است و برای پر کردن فایل کشویی در کنترل ما استفاده می شود.
بدنه سند (documentbody): این ستون حاوی محتوای واقعی فایل پیوست شده است که در رشته فرمت Base64 کدگذاری شده است. این جایی است که داده های فایل ذخیره می شود و آن را به بخش مهمی از مدیریت پیوست تبدیل می کند.
اکنون که درک بهتری از زمینه های مختلف در موجودیت یادداشت داریم، اجازه دهید به ایجاد کنترل خود ادامه دهیم.
افزودن کشویی فایل
اکنون یک منوی کشویی File ایجاد می کنیم که لیست فایل های پیوست شده با رکوردهای یادداشت را نمایش می دهد.
توجه: در CRM، یک رکورد موجودیت میتواند چندین رکورد یادداشت مرتبط به آن داشته باشد، جایی که هر رکورد یادداشت میتواند دارای فقط یک فایل در آن متصل شده است.
بیایید یک تابع به نام ایجاد کنیم createFileOptions که خواهد گرفت notes به عنوان یک پارامتر ثبت می کند و آرایه ای از گزینه ها را برای کشویی برمی گرداند.
// …
function createFileOptions(notes: ArrayRecordstring, any>>)
{
const options: IDropdownOption[] = [];
for(const [index, note] of notes.entries())
{
const option = { key: index, text: note[“filename”] ?? “No File” };
options.push(option);
}
return options;
}
// …
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
این تابع یک آرایه از IDropdownOption اشیاء، با هر شیء حاوی یک ویژگی متنی است که مقدار the را در خود دارد filename فیلد از سوابق یادداشت.
به یاد داشته باشید: notes یک متغیر حالت است که با استفاده از آن ایجاد کردیم parseDatasetToJSON تابع و هر رکورد یادداشت حاوی دو ویژگی اصلی است filename و documentbody
در مرحله بعد، با استفاده از این تابع، داده های این گزینه را در یک ذخیره می کنیم fileOptions متغیر state، و این گزینه را به یک کنترل کشویی Fluent UI منتقل می کند تا در بالای آن اضافه شود DetailsList کنترل در بیانیه بازگشت.
import { DetailsList, Dropdown, IDropdownOption, Stack } from ‘@fluentui/react’;
// …
const [notes, setNotes] = useStateArrayRecordstring, any>>>([]); // Array of JSON objects
const [fileOptions, setFileOptions] = useStateIDropdownOption[]>([]); // Array of IDropdownOption objects
useEffect(() => {
const notesRecords = parseDatasetToJSON();
const fileOptionsRecords = createFileOptions(notesRecords);
setNotes(notesRecords);
setFileOptions(fileOptionsRecords);
}, [sampleDataSet]); // On dataset change
return (
Stack>
Dropdown placeholder=”Select File” options={fileOptions}/>
DetailsList items={notes}/>
/Stack>
);
// …
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
در این مرحله کد App.tsx شما باید چیزی شبیه به این باشد:
import * as React from ‘react’;
import { useState, useEffect } from ‘react’;
import { IInputs } from “./generated/ManifestTypes”;
import { DetailsList, Dropdown, IDropdownOption, Stack } from ‘@fluentui/react’;
export function PCFControl({sampleDataSet} : IInputs) {
function parseDatasetToJSON()
{
const jsonData = [];
for(const recordID of sampleDataSet.sortedRecordIds)
{
// Dataset record
const record = sampleDataSet.records[recordID];
const temp: Recordstring, any> = {};
for(const column of sampleDataSet.columns)
{
temp[column.name] = record.getFormattedValue(column.name)
}
jsonData.push(temp);
}
return jsonData;
}
function createFileOptions(notes: ArrayRecordstring, any>>)
{
const options: IDropdownOption[] = [];
for(const [index, note] of notes.entries())
{
const option = { key: index, text: note[“filename”] ?? “No File” }
options.push(option);
}
return options;
}
const [notes, setNotes] = useStateArrayRecordstring, any>>>([]); // Array of JSON objects
const [fileOptions, setFileOptions] = useStateIDropdownOption[]>([]); // Array of IDropdownOption objects
useEffect(() => {
const notesRecords = parseDatasetToJSON();
const fileOptionsRecords = createFileOptions(notesRecords);
setNotes(notesRecords);
setFileOptions(fileOptionsRecords);
}, [sampleDataSet]); // On dataset change
return (
Stack>
Dropdown placeholder=”Select File” options={fileOptions}/>
DetailsList items={notes}/>
/Stack>
);
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
پروژه خود را بسازید و اکنون یک کشویی در بالای لیست خود اضافه می شود که شامل filename مقادیر از فایل مجموعه داده شما
هنگام ساخت با گفتن خطا مواجه شد غیر منتظره هر. نوع دیگری @typescript-eslint/no-explicit-any را مشخص کنید ?
خوب، زیرا تایپ اسکریپت یک زبان با تایپ قوی است و از ما انتظار دارد که انواع متغیرها را در طول زمان کامپایل تعریف کنیم تا از هرگونه خطای زمان اجرا جلوگیری کنیم.
برای رفع این مشکل، به آدرس خود بروید .eslintrc.json فایل کنید و این تنظیمات را به ویژگی قوانین اضافه کنید، این به ما امکان می دهد از متغیرهای نوع استفاده کنیم any. سپس دوباره پروژه خود را بسازید.
“@typescript-eslint/no-explicit-any”: “off”
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
در حال حاضر از آنجایی که ما در حال استفاده از filename فیلد از سوابق یادداشت، مطمئن شوید که آن را اضافه کرده اید filename ستون در مجموعه داده شما به یاد داشته باشید که فایل مجموعه داده شما نشان دهنده رکوردهای موجودیت یادداشت در CRM است.
برای مرجع در اینجا فایل dataset.csv است که ما برای این آموزش استفاده می کنیم،
در حال حاضر سبک کنترل ها را نادیده بگیرید، ما آنها را در بخش های بعدی اضافه خواهیم کرد.
حال وقتی کاربر یک فایل را از منوی بازشو انتخاب می کند، می خواهیم داده های آن فایل را دریافت کنیم که همانطور که گفته شد در documentbody فیلد رکورد یادداشت
برای پیاده سازی آن، اجازه دهید یک تابع به نام ایجاد کنیم handleSelectFile زمانی که کاربر یک فایل را در منوی کشویی انتخاب می کند، فراخوانی می شود.
با انتخاب یک فایل، این تابع داده های آن فایل را از فایل بازیابی می کند documentbody فیلد، و سپس این داده ها را که در قالب رشته Base64 هستند به یک تبدیل می کند excelWorkbook شی با استفاده از کتابخانه XLSX.
توجه: excelWorkbook شی داده های فایل انتخابی فعلی را ذخیره می کند.
import * as XLSX from ‘xlsx’;
// …
function handleSelectFile(event: React.FormEventHTMLDivElement>, option?: IDropdownOption)
{
if(option === undefined) return; // Return if no option is selected
const note = notes[option.key as number]; // Get note record using index
const base64Data = note[“documentbody”] ?? “”; // Get file data of that note record
const workbook = XLSX.read(base64Data, { type: ‘base64’, cellDates: true }); // Converts base64 data to excel workbook object
setExcelWorkbook(workbook);
console.log(workbook);
}
const [notes, setNotes] = useStateArrayRecordstring, any>>>([]); // Array of JSON objects
const [fileOptions, setFileOptions] = useStateIDropdownOption[]>([]); // Array of IDropdownOption objects
const [excelWorkbook, setExcelWorkbook] = useStateXLSX.WorkBook>(XLSX.utils.book_new()); // Excel workbook object
// …
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
سپس این تابع را در قسمت اضافه کنید onChange ویژگی کشویی، که هر زمان که فایلی در منوی کشویی انتخاب شود، این تابع را فراخوانی می کند.
return (
Stack>
Dropdown placeholder=”Select File” options={fileOptions} onChange={handleSelectFile}/>
DetailsList items={notes}/>
/Stack>
);
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
قبل از اعتبارسنجی بهروزرسانیها، ابتدا ستونی به نام اضافه میکنیم documentbody در فایل مجموعه داده نمونه ما که حاوی مقادیر رشته base64 یک فایل اکسل است. برای تبدیل یک فایل اکسل به رشته base64 می توانید از این ابزار آنلاین استفاده کنید.
توجه: documentbody مقدار نشان دهنده فایل اکسل است که به رکوردهای یادداشت ما در CRM پیوست می شود
در اینجا نمونه فایلی است که استفاده کردیم، که در آن سلول F2 حاوی یک رشته کدگذاری شده base64 از یک فایل اکسل است.
حالا وقتی پروژه خود را می سازیم و فایل را انتخاب می کنیم Sales.xlsx، آن فایل documentbody مقدار بازیابی می شود و به شیء اکسل کتاب کار تبدیل می شود و به کنسول وارد می شود.
اضافه کردن برگه کشویی
تا این مرحله که موفق به دریافت excelWorkbook هنگامی که کاربر یک فایل را در منوی کشویی انتخاب می کند، در کد ما شیء قرار می گیرد. در مراحل بعدی، اکنون میخواهیم تمام برگههای موجود در این کتاب کار را دریافت کرده و در یک برگه کشویی جداگانه نمایش دهیم.
بنابراین اکنون کنترل کشویی برگه را ایجاد می کنیم که لیست برگه های موجود در داخل ما را نمایش می دهد excelWorkbook شی هنگامی که کاربر یک برگه را انتخاب می کند، ما ردیف ها/سوابق این برگه را به فرمت آرایه json تبدیل می کنیم و آن را با استفاده از ما نمایش می دهیم. DetailsList کنترل کنید.
برای آن، ابتدا یک تابع به نام ایجاد می کنیم createSheetOptions که از طریق آن تجزیه خواهد شد workbook شی و لیستی از گزینه های حاوی نام برگه را ایجاد می کند، مشابه کاری که برای گزینه های کشویی فایل انجام دادیم.
// …
function createSheetOptions(workbook: XLSX.WorkBook)
{
const options: IDropdownOption[] = [];
for(const [index, sheetName] of workbook.SheetNames.entries())
{
const option = { key: index, text: sheetName };
options.push(option);
}
return options;
}
// …
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
در مرحله بعد، با استفاده از این تابع، گزینه های این برگه را در یک ذخیره می کنیم sheetOptions متغیر، و این گزینه ها را با استفاده از a نمایش می دهد Dropdown کنترل کنید.
یادش بخیر داشتیم زنگ میزدیم createFileOptions هنگامی که مجموعه داده در کنترل ما از روی بارگیری یا تغییر می کند useEffect تابع حالا چه زمانی باید با آن تماس بگیریم createSheetOptions ?
درسته! باید به محض اینکه کاربر یک فایل را انتخاب کرد، یعنی داخل، فراخوانی شود handleSelectFile تابع با این کار هر زمان که کاربر یک فایل را انتخاب کند، ما sheetOptions بر اساس فایل انتخابی به روز می شود.
بیایید به روز رسانی کنیم handleSelectFile عملکرد برای رسیدن به همان،
// …
function handleSelectFile(event: React.FormEventHTMLDivElement>, option?: IDropdownOption)
{
if(option === undefined) return; // Return if no option is selected
const note = notes[option.key as number]; // Get note record using index
const base64Data = note[“documentbody”] ?? “”; // Get file data
const workbook = XLSX.read(base64Data, { type: ‘base64’, cellDates: true }); // Converts base64 data to excel workbook object
setExcelWorkbook(workbook);
const sheetOptionsRecords = createSheetOptions(workbook);
setSheetOptions(sheetOptionsRecords);
}
const [notes, setNotes] = useStateArrayRecordstring, any>>>([]); // Array of JSON objects
const [fileOptions, setFileOptions] = useStateIDropdownOption[]>([]); // Array of IDropdownOption objects
const [excelWorkbook, setExcelWorkbook] = useStateXLSX.WorkBook>(XLSX.utils.book_new()); // Excel workbook object
const [sheetOptions, setSheetOptions] = useStateIDropdownOption[]>([]); // Array of IDropdownOption objects
// …
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
حالا بیایید یک کنترل کشویی جدید در عبارت بازگشت خود اضافه کنیم که اینها را نمایش می دهد sheetOptions به کاربر.
return (
Stack>
Stack horizontal>
Dropdown placeholder=”Select File” options={fileOptions} onChange={handleSelectFile}/>
Dropdown placeholder=”Select Sheet” options={sheetOptions} />
/Stack>
DetailsList items={notes}/>
/Stack>
);
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
ما برگهها را در فهرست کشویی خود دریافت کردیم، برای مرحله بعدی، میخواهیم هر زمان که کاربر برگهای را در فهرست کشویی انتخاب کرد، ردیفها/سوابق برگه باید در صفحه نمایش داده شوند. DetailsList کنترل کنید.
برای رسیدن به آن، اجازه دهید یک تابع به نام ایجاد کنیم handleSelectSheet هر زمان که کاربر برگه را در منوی کشویی انتخاب کند، فراخوانی می شود.
این تابع برگه انتخاب شده فعلی را از excelWorkbook شی در کد ما ذخیره می شود و آن رکورد/ردیف برگه را به یک آرایه json تبدیل می کند. سپس این داده های json را در یک متغیر حالت به نام ذخیره می کنیم rows که می تواند به ما منتقل شود DetailsList کنترل کنید.
function handleSelectSheet(event: React.FormEventHTMLDivElement>, option?: IDropdownOption)
{
if(option === undefined) return; // Return if no option is selected
const sheet = excelWorkbook.Sheets[option.text as string]; // Get sheet record using SheetName
const rowRecords: Recordstring, any>[] = XLSX.utils.sheet_to_json(sheet, {raw: false}); // Sheet Records in JSON Array
setRows(rowRecords);
}
const [notes, setNotes] = useStateArrayRecordstring, any>>>([]); // Array of JSON objects
const [fileOptions, setFileOptions] = useStateIDropdownOption[]>([]); // Array of IDropdownOption objects
const [excelWorkbook, setExcelWorkbook] = useStateXLSX.WorkBook>(XLSX.utils.book_new()); // Excel workbook object
const [sheetOptions, setSheetOptions] = useStateIDropdownOption[]>([]); // Array of IDropdownOption objects
const [rows, setRows] = useStateArrayRecordstring, any>>>([]); // Array of JSON objects
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
حالا این تابع را در قسمت اضافه کنید onChange ویژگی برگه کشویی که این تابع را هنگام انتخاب یک برگه فراخوانی می کند و به روز رسانی می کند items دارایی از DetailsList کنترل برای استفاده از rows داده هایی که شامل سوابق برگه انتخابی ما هستند.
return (
Stack>
Stack horizontal>
Dropdown placeholder=”Select File” options={fileOptions} onChange={handleSelectFile}/>
Dropdown placeholder=”Select Sheet” options={sheetOptions} onChange={handleSelectSheet} />
/Stack>
DetailsList items={rows}/>
/Stack>
);
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
افزودن دکمه دانلود
قبل از اینکه به جلو برویم و کنترل خود را آزمایش کنیم، اجازه دهید ابتدا قسمت نهایی عملکرد کنترل PCF خود را اضافه کنیم، یعنی قابلیت دانلود فایل.
هر زمان که کاربر بر روی دکمه دانلود کلیک کند، فایل انتخابی فعلی را دانلود می کند (ذخیره شده در excelWorkbook شی) در سیستم کاربر.
ما می توانیم این را با اجرای ساده اجرا کنیم XLSX.writeFile() روش بر روی onClick کنترل دکمه این متد شیء کتاب کار را به عنوان پارامتر اول و نام فایلی که باید دانلود شود را به عنوان پارامتر دوم در نظر می گیرد.
بیایید یک را ایجاد کنیم PrimaryButton به همراه سایر کنترل های کشویی کنترل کنید و تابعی به نام اجرا کنید handleDownload با استفاده از onClick ویژگی کنترل دکمه
// …
function handleDownload()
{
XLSX.writeFile(excelWorkbook, ‘download.xlsx’);
}
// …
return (
Stack>
Stack horizontal>
Dropdown placeholder=”Select File” options={fileOptions} onChange={handleSelectFile}/>
Dropdown placeholder=”Select Sheet” options={sheetOptions} onChange={handleSelectSheet} />
PrimaryButton text=”Download” allowDisabledFocus onClick={handleDownload}/>
/Stack>
DetailsList items={rows}/>
/Stack>
);
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
حال با کلیک بر روی دکمه دانلود فایل انتخابی در سیستم شما دانلود می شود.
در این مرحله شما App.tsx کد باید چیزی شبیه به این باشد:
import * as React from ‘react’;
import { useState, useEffect } from ‘react’;
import { IInputs } from “./generated/ManifestTypes”;
import { DetailsList, DetailsListLayoutMode, Dropdown, IDropdownOption, PrimaryButton, Stack } from ‘@fluentui/react’;
import * as XLSX from ‘xlsx’;
import { text } from ‘stream/consumers’;
export function PCFControl({sampleDataSet} : IInputs) {
function parseDatasetToJSON()
{
const jsonData = [];
for(const recordID of sampleDataSet.sortedRecordIds)
{
// Dataset record
const record = sampleDataSet.records[recordID];
const temp: Recordstring, any> = {};
for(const column of sampleDataSet.columns)
{
temp[column.name] = record.getFormattedValue(column.name)
}
jsonData.push(temp);
}
return jsonData;
}
function createFileOptions(notes: ArrayRecordstring, any>>)
{
const options: IDropdownOption[] = [];
for(const [index, note] of notes.entries())
{
const option = { key: index, text: note[“filename”] ?? “No File” };
options.push(option);
}
return options;
}
function createSheetOptions(workbook: XLSX.WorkBook)
{
const options: IDropdownOption[] = [];
for(const [index, sheetName] of workbook.SheetNames.entries())
{
const option = { key: index, text: sheetName };
options.push(option);
}
return options;
}
function handleSelectFile(event: React.FormEventHTMLDivElement>, option?: IDropdownOption)
{
if(option === undefined) return; // Return if no option is selected
const note = notes[option.key as number]; // Get note record using index
const base64Data = note[“documentbody”] ?? “”; // Get file data
const workbook = XLSX.read(base64Data, { type: ‘base64’, cellDates: true }); // Converts base64 data to excel workbook object
setExcelWorkbook(workbook);
const sheetOptionsRecords = createSheetOptions(workbook);
setSheetOptions(sheetOptionsRecords);
}
function handleSelectSheet(event: React.FormEventHTMLDivElement>, option?: IDropdownOption)
{
if(option === undefined) return; // Return if no option is selected
const sheet = excelWorkbook.Sheets[option.text as string]; // Get sheet record using SheetName
const rowRecords: Recordstring, any>[] = XLSX.utils.sheet_to_json(sheet, {raw: false}); // Sheet Records in JSON Array
setRows(rowRecords);
}
function handleDownload()
{
XLSX.writeFile(excelWorkbook, ‘download.xlsx’);
}
const [notes, setNotes] = useStateArrayRecordstring, any>>>([]); // Array of JSON objects
const [fileOptions, setFileOptions] = useStateIDropdownOption[]>([]); // Array of IDropdownOption objects
const [excelWorkbook, setExcelWorkbook] = useStateXLSX.WorkBook>(XLSX.utils.book_new()); // Excel workbook object
const [sheetOptions, setSheetOptions] = useStateIDropdownOption[]>([]); // Array of IDropdownOption objects
const [rows, setRows] = useStateArrayRecordstring, any>>>([]); // Array of JSON objects
useEffect(() => {
const notesRecords = parseDatasetToJSON();
const fileOptionsRecords = createFileOptions(notesRecords);
setNotes(notesRecords);
setFileOptions(fileOptionsRecords);
}, [sampleDataSet]); // On dataset change
return (
Stack>
Stack horizontal>
Dropdown placeholder=”Select File” options={fileOptions} onChange={handleSelectFile}/>
Dropdown placeholder=”Select Sheet” options={sheetOptions} onChange={handleSelectSheet} />
PrimaryButton text=”Download” allowDisabledFocus onClick={handleDownload}/>
/Stack>
DetailsList items={rows}/>
/Stack>
);
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
اکنون وقتی کنترل را میسازید، در منوی کشویی فایلها، همه فایلهای فهرست شده توسط را مشاهده خواهید کرد filename ستون (این نشان دهنده نام فایلی است که به رکوردهای یادداشت در CRM پیوست شده است).
هنگامی که یک فایل را انتخاب می کنید، در کد documentbody ارزش (این نشان دهنده فایل واقعی است که به رکورد یادداشت در CRM پیوست شده است) از آن فایل به یک کتاب کار اکسل تبدیل میشود و برگههای آن در برگههای کشویی نمایش داده میشود.
پس از انتخاب یک شیت، رکوردهای آن شیت به آرایه json تبدیل شده و در لیست نمایش داده می شود.
توجه: برای تبدیل یک فایل اکسل به رشته base64 می توانید از این ابزار آنلاین استفاده کنید.
برای مرجع، این فایل مجموعه داده اکسل است که ما برای این آموزش استفاده کردیم،
یک ظاهر طراحی را به کنترل ها اضافه کنید
کار عالی تا اینجا در آموزش…
اکنون که عملکرد اصلی این کنترل PCF را پیادهسازی کردهایم، بیایید برای تجربه کاربری بهتر، سبکی به کنترل خود اضافه کنیم.
یک فایل جدید ایجاد کنید ControlStyles.tsx در پوشه پروژه خود و ویژگی های سبک زیر را در آن فایل اضافه کنید.
/* ControlStyles.tsx */
import { IStackTokens, IStackStyles, IDetailsListStyles, IDropdownStyles } from “@fluentui/react”;
export const stackTokens: IStackTokens = {
childrenGap: 10
};
export const stackStyles: IStackStyles = {
root: {
padding: 10,
width: ‘100%’,
marginBottom: 20,
},
};
export const detailsListStyles: IDetailsListStyles = {
root: {
overflowX: ‘auto’
},
contentWrapper: {
overflowY: ‘auto’,
width: ‘max-content’,
height: 450
},
focusZone : {},
headerWrapper: {}
}
export const dropDownStyles : PartialIDropdownStyles> = {
root : {
width: ‘auto’,
minWidth: 200
}
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
سپس این ویژگی های سبک را در اصلی ما وارد کنید App.tsx فایل و این ویژگی ها را در کنترل های Fluent UI ما اضافه کنید.
// …
import {stackTokens, stackStyles, detailsListStyles, dropDownStyles} from ‘./ControlStyles’
// …
return (
Stack tokens={stackTokens} styles={stackStyles}>
Stack horizontal tokens={stackTokens} styles={stackStyles}>
Dropdown
placeholder=”Select File”
options={fileOptions}
onChange={handleSelectFile}
styles={dropDownStyles}
/>
Dropdown
placeholder=”Select Sheet”
options={sheetOptions}
onChange={handleSelectSheet}
styles={dropDownStyles}
defaultSelectedKey=’0′
/>
PrimaryButton text=”Download” allowDisabledFocus onClick={handleDownload}/>
/Stack>
DetailsList
items={rows}
styles={detailsListStyles}
data-is-scrollable={false}
layoutMode={DetailsListLayoutMode.fixedColumns}
/>
/Stack>
);
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
پروژه خود را بسازید و می توانید کنترل PCF استایل خود را در عمل ببینید،
جمع بندی نهایی
هنگامی که کنترل PCF خود را به یک شبکه متصل می کنید، کنترل به مجموعه داده های ارائه شده توسط آن شبکه مشترک می شود. فیلدها و رکوردهایی که برای نمایش در شبکه پیکربندی شدهاند به ویژگی مجموعه داده کنترل PCF شما منتقل میشوند و به آن اجازه میدهند این دادهها را به شیوهای سفارشیشده ارائه یا پردازش کند.
با این حال، برخی از ستون های خاص مانند documentbody در note موجودیت برای افزودن مستقیم به شبکه در دسترس نیست زیرا یک فیلد باینری است و Dynamics CRM به دلیل نگرانیهای مربوط به عملکرد و قابلیت استفاده، اجازه نمیدهد فیلدهای باینری در نماهای شبکه نمایش داده شوند.
بنابراین برای دسترسی به documentbody و filename دادههای ستونها، میتوانیم این کار را با افزودن برنامهنویسی آن ستونها در مجموعه داده خود انجام دهیم. بیایید این ستون ها را به ما اضافه کنیم sampleDataSet اموال از updateView روش در index.ts فایل
// …
public updateView(context: ComponentFramework.ContextIInputs>): React.ReactElement
{
if (context.parameters.sampleDataSet.addColumn)
{
context.parameters.sampleDataSet.addColumn(“documentbody”);
context.parameters.sampleDataSet.addColumn(“filename”);
context.parameters.sampleDataSet.refresh();
}
const props: IInputs = { sampleDataSet: context.parameters.sampleDataSet };
return React.createElement(PCFControl, props);
}
// …
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
استقرار کنترل PCF
زمان آن رسیده است که کنترل PCF خود را از طریق Power Apps در عمل مشاهده کنیم.
برای استقرار کنترل PCF خود در محیط Power Apps، دستورات زیر را در ترمینال اجرا کنید.
npm run build
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
با محیط برنامه های قدرت خود ارتباط برقرار کنید،
pac auth create –environment “{Your Environment Name}”
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
کنترل را در محیط خود مستقر کنید،
pac pcf push
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
پس از استقرار موفقیت آمیز، به make.powerapps.com بروید:
محیط خود را انتخاب کنید: محیطی را که کنترل را در آن مستقر کرده اید انتخاب کنید.
به راه حل ها بروید: به Solutions > Default Solution > Custom Controls بروید.
کنترل خود را بررسی کنید: کنترل PCF شما باید در لیست ظاهر شود.
اضافه کردن کنترل در Grid
برای این آموزش، کنترل خود را بر روی شبکه یادداشتها در فرم جدول حساب ضمیمه میکنیم.
توجه: میتوانید این کنترل را در هر فرم موجودی که فعال باشد تا پیوستهایی با آن پیوند داده شود، اضافه کنید.
جدول مربوطه را به عنوان یادداشت در زیرشبکه انتخاب کنید.
فیلترهای کلیدی را که باید در نمای یادداشتهای خود اضافه کنید، افزودن این فیلترها در نمای، تضمین میکند که فقط آن رکوردهای یادداشت را به مجموعه داده ما بازگردانید که یک فایل اکسل به آنها پیوست شده است.
سپس به Get More Components و جستجو کنید ReactDatasetControl که به تازگی ایجاد کرده و به لیست اضافه کرده ایم.
آن کنترل را به شبکه اضافه کنید و فرم را ذخیره و منتشر کنید.
هر رکورد حسابی را که دارای یادداشت هایی با پیوست های اکسل است باز کنید و باید بتوانید فایل های خود را در کنترل مشاهده کنید.
بسته شدن
تبریک می گویم! شما یک کنترل مجموعه داده PCF سفارشی ایجاد کرده اید که:
نمایش یادداشتهای پیوست اکسل در برنامههای مبتنی بر مدل،
هر برگه را در فایل اکسل فهرست می کند،
فایل را درون سیستم دانلود می کند.
از کنترلهای Fluent UI React استفاده میکند که توسط مایکروسافت برای توسعه برنامههای Dynamics مدرن ساخته شدهاند.
کار خوب! امیدوارم اکنون احساس کنید که درک مناسبی از کنترلهای React و PCF در دینامیک دارید.
اگر میخواهید مهارتهای کنترلی React و PCF خود را بیشتر تقویت کنید، در اینجا ایدههایی برای بهبودهایی وجود دارد که میتوانید در این کنترل انجام دهید:
منطق رسیدگی به خطا را اضافه کنید تا نیازی به فیلترهای مشاهده نباشد.
قابلیت مرتب سازی، فیلتر و جستجو را در کنترل گرید DetailsList اضافه کنید.
برای خواندن انواع دیگر فایلها مانند txt، pdf، docx و غیره، پشتیبانی اضافه کنید.
ویژگی های CRUD را در شبکه اضافه کنید.
میتوانید سایر ویژگیهای جالبی را که میتوان اضافه کرد یا تردیدهای خود را در مورد این آموزش در بخش نظرات به اشتراک بگذارید.
در اینجا مخزن GitHub برای این پروژه است.
کدنویسی مبارک…
در این آموزش، شما یک کنترل داده تعاملی PCF را با استفاده از React ایجاد میکنید که میتواند در شبکه موجودیت Dynamics CRM ادغام شود.
تکنیک هایی که در این آموزش خواهید آموخت به شما درک عمیق تری از کنترل های PCF در Dynamics CRM می دهد. در سراسر این راهنما، ما همه چیز را از راهاندازی محیط توسعه تا استقرار و آزمایش کنترل سفارشی شما پوشش خواهیم داد.
چی میسازی؟
در این آموزش، کنترلی خواهید ساخت که فایل اکسل پیوست شده به یادداشتهای درون CRM را نمایش میدهد و به کاربران روشی بصریتر و سازماندهیشدهتر برای دسترسی به پیوستهای اکسل مرتبط با رکوردهای یادداشت ارائه میدهد.
در اینجا میتوانید ببینید که وقتی کارتان تمام شد چگونه به نظر میرسد:
در برگه Timeline، سه یادداشت مرتبط با حساب وجود دارد که هر کدام یک فایل اکسل پیوست شده است.
در تب Notes، کنترل سفارشی ما اضافه شده است که این فایلهای اکسل را استخراج کرده و در منوی انتخاب فایل فهرست میکند و با انتخاب فایل، برگههای آن فایل اکسل در منوی انتخاب برگه نمایش داده میشود.
وقتی کاربر برگهای را انتخاب میکند، دادههای آن مطابق شکل بالا در شبکه نمایش داده میشود، و همانطور که متوجه شدید ما یک قابلیت دانلود سفارشی نیز ایجاد میکنیم که فایل انتخابی را در سیستم ما دانلود میکند.
راه اندازی برای آموزش
قبل از شروع ساختن کنترلهای PCF با React، مطمئن شوید که ابزارهای لازم را روی دستگاه خود نصب کردهاید:
-
Node.js: نسخه LTS توصیه می شود
-
کد ویژوال استودیو (VS Code): برای تجربه بهتر کدنویسی توصیه می شود از ویرایشگری مانند Visual Studio Code استفاده کنید.
-
Microsoft Power Platform CLI: برای نصب Power Platform CLI از ابزارهای Power Platform برای VS Code یا Power Platform CLI برای ویندوز استفاده کنید.
ایجاد یک پروژه جدید
هنگامی که محیط شما آماده شد، یک پروژه کنترل مجموعه داده PCF جدید ایجاد کنید.
-
کد ویژوال استودیو را باز کنید و از ترمینال به پوشه ای که می خواهید پروژه کنترل PCF را در آن ایجاد کنید بروید.
-
دستور زیر را از ترمینال خود برای ایجاد یک پروژه کنترل PCF جدید اجرا کنید:
pac pcf init --namespace SampleNamespace --name ReactDatasetControl --template dataset --framework react --run-npm-install
-
--namespace
فضای نام را برای کنترل شما مشخص می کند. -
--name
نام کنترل شما را مشخص می کند. -
--template
نوع کنترل را مشخص می کند (مثلاً فیلد یا مجموعه داده) -
--framework
(اختیاری) چارچوب کنترل را مشخص می کند. -
--run-npm-install
ماژول های گره مورد نیاز را برای کنترل نصب می کند.
اجرای موارد بالا pac pcf init
فرمان یک کنترل PCF اولیه را با تمام فایلها و وابستگیهای مورد نیاز تنظیم میکند و آن را برای سفارشیسازی و استقرار در PowerApps آماده میکند.
در این آموزش ما از کتابخانه XLSX برای کار با فایل های اکسل استفاده می کنیم. آنها را در پروژه خود با استفاده از
npm install xlsx
npm install --save-dev ajv
نمای کلی
اکنون که راه اندازی شده اید، بیایید مروری بر PCF Dataset Control داشته باشیم!
بررسی کد شروع
در کاوشگر سه بخش اصلی را مشاهده خواهید کرد:
-
node_modules شامل تمام بسته های گره مورد نیاز برای پروژه است.
-
ReactDatasetControl پوشه پروژه حاوی فایل های اصلی است.
-
eslintrc.json
،package.json
فایل های پیکربندی پروژه هستند.
بیایید نگاهی به برخی از فایل های کلیدی بیندازیم.
ControlManifest.Input.xml
اینجا جایی است که پیکربندی و ویژگی های کنترل PCF خود را تعریف می کنید. این شامل اطلاعاتی مانند نام کنترل، نسخه، توضیحات و انواع داده هایی است که می پذیرد.
index.ts
این به عنوان نقطه ورود برای منطق تجاری کنترل PCF شما عمل می کند. جایی است که شما رفتار و تعاملات کنترل خود را تعریف می کنید.
روش های چرخه زندگی:
-
init
: این متد زمانی فراخوانی می شود که کنترل مقداردهی اولیه شود. برای راهاندازی کنترل، از جمله کنترلکنندههای رویداد، و رندر کردن رابط کاربری اولیه استفاده میشود. -
updateView
: هر زمان که کنترل نیاز به به روز رسانی داشته باشد، این روش فراخوانی می شود، برای مثال زمانی که داده ها یا ویژگی های کنترل تغییر می کند. برای رندر مجدد رابط کاربری با آخرین داده ها استفاده می شود. -
getOutputs
: این متد مقدار فعلی خروجی های کنترل را برمی گرداند که می تواند توسط اجزای دیگر استفاده شود یا در پایگاه داده ذخیره شود. -
destroy
: این متد زمانی فراخوانی می شود که کنترل از DOM حذف شود. برای پاکسازی منابع، مانند کنترل کننده رویدادها، برای جلوگیری از نشت حافظه استفاده می شود.
در کنترل ما، updateView
متد زمانی فراخوانی می شود که صفحه بارگیری می شود. این روش رندر می کند HelloWorld
جزء از HelloWorld.tsx
فایل
ساخت جزء
بیایید با ایجاد یک فایل App.tsx در داخل پوشه پروژه ReactDatasetControl شروع کنیم. این منطق کنترل PCF ما را تشکیل می دهد.
/* App.tsx */
import * as React from 'react';
import { IInputs } from "./generated/ManifestTypes";
import { DetailsList } from '@fluentui/react';
export function PCFControl({sampleDataSet} : IInputs) {
const records = [
{
"First Name": "Saturo",
"Last Name": "Gojo",
"Domain": "Infinity Void"
},
{
"First Name": "Sukuna",
"Last Name": "Ryomen",
"Domain": "Malevolent Shrine"
}
];
return DetailsList items={records}/>
}
-
خطوط 1-3 تمام واردات لازم برای کنترل را به ارمغان می آورد.
-
خط بعدی تابعی به نام تعریف می کند
PCFControl
. راexport
کلیدواژه جاوا اسکریپت این تابع را خارج از این فایل قابل دسترسی می کند. -
در
PCFControl
تابع asampleDataSet
ویژگی ارسال می شود که شامل داده ها/سوابق شبکه ای است که کنترل ما به آنها متصل می شود. -
تابع a را برمی گرداند
DetailsList
کنترل با سوابق داده های ارسال شده به آنitems
دارایی -
DetailsList
یک کنترل واکنش Fluent UI ایجاد شده توسط مایکروسافت است که برای مشاهده داده ها در قالب لیست استفاده می شود.
index.ts
فایل با عنوان را باز کنید index.ts
، ما را وارد کنید PCFControl
در بالای فایل و اجازه دهید تغییر دهید updateView
تابعی برای برگرداندن کنترل سفارشی ما.
import { PCFControl } from "./App"
// ...
public updateView(context: ComponentFramework.ContextIInputs>): React.ReactElement
{
const props: IInputs = { sampleDataSet: context.parameters.sampleDataSet };
return React.createElement(PCFControl, props);
}
// ...
context.parameters.sampleDataSet
به ویژگی مجموعه داده از context
پارامتر این شامل داده ها/سوابق شبکه ای است که کنترل ما در بخش های بعدی به آن ملزم خواهد شد. سپس یک عنصر React متشکل از PCFControl
مؤلفه و مجموعه داده ارسالی props
به عنوان خواص به آن.
اکنون که یک ساختار اساسی برای کنترل خود ایجاد کرده ایم، بیایید کنترل خود را بسازیم و اجرا کنیم تا ببینیم ظاهر آن چگونه است. برای مشاهده کنترل در مرورگر محلی خود دستورات زیر را در ترمینال اجرا کنید.
npm run build
npm start watch
اکنون می توانید رکوردهای خود را در قالب لیست جدولی مشاهده کنید،
استفاده از داده ها از طریق props
در مرحله بعدی، میخواهیم دادههای شبکه CRM را که از آن دریافت میکنیم، نمایش دهیم sampleDataSet
ویژگی در کنترل به جای استفاده از رکوردهای داده استاتیک.
باز کنید App.tsx
و اجازه دهید ابتدا یک تابع به نام ایجاد کنیم parseDatasetToJSON
در داخل تابع PCFControl، که آن را تجزیه می کند sampleDataSet
ویژگی (شامل داده های شبکه) و آن داده ها را در آرایه ای از اشیاء json برمی گرداند.
// ...
function parseDatasetToJSON()
{
const jsonData = [];
for(const recordID of sampleDataSet.sortedRecordIds)
{
// Dataset record
const record = sampleDataSet.records[recordID];
const temp: Recordstring, any> = {};
// Loop through each dataset columns
for(const column of sampleDataSet.columns)
{
temp[column.name] = record.getFormattedValue(column.name)
}
jsonData.push(temp);
}
return jsonData;
}
// ...
اکنون که تابعی برای تبدیل مجموعه داده به JSON دریافت کردهایم، میخواهیم این تابع را بهسرعت فراخوانی کنیم sampleDataSet
دارایی بارگیری یا تغییر کرده است.
React یک توابع ویژه به نام ارائه می کند قلاب، مانند useState
که به شما این امکان را می دهد که داده های خود را در یک متغیر ویژگی نوع حالت و useEffect
به شما امکان می دهد توابع مربوط به هر یک از تغییر ویژگی نوع حالت را فراخوانی کنید.
بیشتر بدانید useState
و useEffect
از،
واردات useState
و useEffect
در بالای فایل، سپس یک متغیر حالت به نام را مقداردهی اولیه کنید notes
که رکوردهای مجموعه داده با فرمت JSON ما را ذخیره می کند.
زمانی که sampleDataSet
دارایی بارگیری/تغییر شده است، useEffect
تابع فراخوانی می شود و notes
متغیر با رکوردهای مجموعه داده جدید به روز می شود.
سپس DetailsList را به روز می کنیم items
دارایی برای استفاده notes
داده ها به جای سوابق داده های ایستا.
import { useState, useEffect } from 'react';
// ...
const [notes, setNotes] = useStateArrayRecordstring, any>>>([]); // Array of JSON Objects
useEffect(() => {
const notesRecords = parseDatasetToJSON();
setNotes(notesRecords);
}, [sampleDataSet]); // On dataset property load or change
return DetailsList items={notes}/>
// ...
در این مرحله شما App.tsx
کد باید چیزی شبیه به این باشد:
import * as React from 'react';
import { useState, useEffect } from 'react';
import { IInputs } from "./generated/ManifestTypes";
import { DetailsList } from '@fluentui/react';
export function PCFControl({sampleDataSet} : IInputs) {
function parseDatasetToJSON()
{
const jsonData = [];
for(const recordID of sampleDataSet.sortedRecordIds)
{
// Dataset record
const record = sampleDataSet.records[recordID];
const temp: Recordstring, any> = {};
// Loop through each dataset columns
for(const column of sampleDataSet.columns)
{
temp[column.name] = record.getFormattedValue(column.name)
}
jsonData.push(temp);
}
return jsonData;
}
const [notes, setNotes] = useStateArrayRecordstring, any>>>([]); // Array of JSON Objects
useEffect(() => {
const notesRecords = parseDatasetToJSON();
setNotes(notesRecords);
}, [sampleDataSet]); // On dataset property load or change
return DetailsList items={notes}/>
}
اکنون پروژه خود را بسازید، و باید چیزی شبیه به این را ببینید،
در بارگذاری، کنترل مجموعه داده PCF این مجموعه داده ساختگی را فراهم می کند. برای ارائه مجموعه داده های سفارشی خود، از قسمت هایلایت شده پایین سمت راست، هر فایل اکسلی را که حاوی لیستی از ستون ها و ردیف ها باشد، انتخاب کنید. در انتخاب PCF Dataset Control این فایل اکسل را به sampleDataSet
دارایی
درک موجودیت CRM: یادداشت ها
در این آموزش ما در حال ایجاد یک کنترل مجموعه داده PCF برای استفاده در موجودیت OOB Notes Dynamics CRM هستیم. بیایید یک لحظه کوتاه به مرور برخی از ستونهای کلیدی موجودیت Notes که بعداً در کنترل ما استفاده خواهند شد، اختصاص دهیم.
را یادداشت ها موجودیت در Dynamics CRM برای ذخیره و مدیریت پیوستها یا نظرات مرتبط با سایر نهادها، مانند حسابها، مخاطبین یا فرصتها استفاده میشود. اغلب برای پیگیری پرونده ها یا یادداشت های مهم مربوط به سوابق استفاده می شود.
در اینجا یک نمای کلی از ستونهای کلیدی موجودیت Notes آورده شده است:
-
نام فایل (
filename
): این ستون نام فایل پیوست شده به یادداشت را ذخیره می کند. این یک فیلد رشته ای است و برای پر کردن فایل کشویی در کنترل ما استفاده می شود. -
بدنه سند (
documentbody
): این ستون حاوی محتوای واقعی فایل پیوست شده است که در رشته فرمت Base64 کدگذاری شده است. این جایی است که داده های فایل ذخیره می شود و آن را به بخش مهمی از مدیریت پیوست تبدیل می کند.
اکنون که درک بهتری از زمینه های مختلف در موجودیت یادداشت داریم، اجازه دهید به ایجاد کنترل خود ادامه دهیم.
افزودن کشویی فایل
اکنون یک منوی کشویی File ایجاد می کنیم که لیست فایل های پیوست شده با رکوردهای یادداشت را نمایش می دهد.
توجه: در CRM، یک رکورد موجودیت میتواند چندین رکورد یادداشت مرتبط به آن داشته باشد، جایی که هر رکورد یادداشت میتواند دارای فقط یک فایل در آن متصل شده است.
بیایید یک تابع به نام ایجاد کنیم createFileOptions
که خواهد گرفت notes
به عنوان یک پارامتر ثبت می کند و آرایه ای از گزینه ها را برای کشویی برمی گرداند.
// ...
function createFileOptions(notes: ArrayRecordstring, any>>)
{
const options: IDropdownOption[] = [];
for(const [index, note] of notes.entries())
{
const option = { key: index, text: note["filename"] ?? "No File" };
options.push(option);
}
return options;
}
// ...
این تابع یک آرایه از IDropdownOption
اشیاء، با هر شیء حاوی یک ویژگی متنی است که مقدار the را در خود دارد filename
فیلد از سوابق یادداشت.
به یاد داشته باشید:
notes
یک متغیر حالت است که با استفاده از آن ایجاد کردیمparseDatasetToJSON
تابع و هر رکورد یادداشت حاوی دو ویژگی اصلی استfilename
وdocumentbody
در مرحله بعد، با استفاده از این تابع، داده های این گزینه را در یک ذخیره می کنیم fileOptions
متغیر state، و این گزینه را به یک کنترل کشویی Fluent UI منتقل می کند تا در بالای آن اضافه شود DetailsList
کنترل در بیانیه بازگشت.
import { DetailsList, Dropdown, IDropdownOption, Stack } from '@fluentui/react';
// ...
const [notes, setNotes] = useStateArrayRecordstring, any>>>([]); // Array of JSON objects
const [fileOptions, setFileOptions] = useStateIDropdownOption[]>([]); // Array of IDropdownOption objects
useEffect(() => {
const notesRecords = parseDatasetToJSON();
const fileOptionsRecords = createFileOptions(notesRecords);
setNotes(notesRecords);
setFileOptions(fileOptionsRecords);
}, [sampleDataSet]); // On dataset change
return (
Stack>
Dropdown placeholder="Select File" options={fileOptions}/>
DetailsList items={notes}/>
/Stack>
);
// ...
در این مرحله کد App.tsx شما باید چیزی شبیه به این باشد:
import * as React from 'react';
import { useState, useEffect } from 'react';
import { IInputs } from "./generated/ManifestTypes";
import { DetailsList, Dropdown, IDropdownOption, Stack } from '@fluentui/react';
export function PCFControl({sampleDataSet} : IInputs) {
function parseDatasetToJSON()
{
const jsonData = [];
for(const recordID of sampleDataSet.sortedRecordIds)
{
// Dataset record
const record = sampleDataSet.records[recordID];
const temp: Recordstring, any> = {};
for(const column of sampleDataSet.columns)
{
temp[column.name] = record.getFormattedValue(column.name)
}
jsonData.push(temp);
}
return jsonData;
}
function createFileOptions(notes: ArrayRecordstring, any>>)
{
const options: IDropdownOption[] = [];
for(const [index, note] of notes.entries())
{
const option = { key: index, text: note["filename"] ?? "No File" }
options.push(option);
}
return options;
}
const [notes, setNotes] = useStateArrayRecordstring, any>>>([]); // Array of JSON objects
const [fileOptions, setFileOptions] = useStateIDropdownOption[]>([]); // Array of IDropdownOption objects
useEffect(() => {
const notesRecords = parseDatasetToJSON();
const fileOptionsRecords = createFileOptions(notesRecords);
setNotes(notesRecords);
setFileOptions(fileOptionsRecords);
}, [sampleDataSet]); // On dataset change
return (
Stack>
Dropdown placeholder="Select File" options={fileOptions}/>
DetailsList items={notes}/>
/Stack>
);
}
پروژه خود را بسازید و اکنون یک کشویی در بالای لیست خود اضافه می شود که شامل filename
مقادیر از فایل مجموعه داده شما
هنگام ساخت با گفتن خطا مواجه شد غیر منتظره هر. نوع دیگری @typescript-eslint/no-explicit-any را مشخص کنید ?
خوب، زیرا تایپ اسکریپت یک زبان با تایپ قوی است و از ما انتظار دارد که انواع متغیرها را در طول زمان کامپایل تعریف کنیم تا از هرگونه خطای زمان اجرا جلوگیری کنیم.
برای رفع این مشکل، به آدرس خود بروید .eslintrc.json
فایل کنید و این تنظیمات را به ویژگی قوانین اضافه کنید، این به ما امکان می دهد از متغیرهای نوع استفاده کنیم any
. سپس دوباره پروژه خود را بسازید.
"@typescript-eslint/no-explicit-any": "off"
در حال حاضر از آنجایی که ما در حال استفاده از filename
فیلد از سوابق یادداشت، مطمئن شوید که آن را اضافه کرده اید filename
ستون در مجموعه داده شما به یاد داشته باشید که فایل مجموعه داده شما نشان دهنده رکوردهای موجودیت یادداشت در CRM است.
برای مرجع در اینجا فایل dataset.csv است که ما برای این آموزش استفاده می کنیم،
در حال حاضر سبک کنترل ها را نادیده بگیرید، ما آنها را در بخش های بعدی اضافه خواهیم کرد.
حال وقتی کاربر یک فایل را از منوی بازشو انتخاب می کند، می خواهیم داده های آن فایل را دریافت کنیم که همانطور که گفته شد در documentbody
فیلد رکورد یادداشت
برای پیاده سازی آن، اجازه دهید یک تابع به نام ایجاد کنیم handleSelectFile
زمانی که کاربر یک فایل را در منوی کشویی انتخاب می کند، فراخوانی می شود.
با انتخاب یک فایل، این تابع داده های آن فایل را از فایل بازیابی می کند documentbody
فیلد، و سپس این داده ها را که در قالب رشته Base64 هستند به یک تبدیل می کند excelWorkbook
شی با استفاده از کتابخانه XLSX.
توجه:
excelWorkbook
شی داده های فایل انتخابی فعلی را ذخیره می کند.
import * as XLSX from 'xlsx';
// ...
function handleSelectFile(event: React.FormEventHTMLDivElement>, option?: IDropdownOption)
{
if(option === undefined) return; // Return if no option is selected
const note = notes[option.key as number]; // Get note record using index
const base64Data = note["documentbody"] ?? ""; // Get file data of that note record
const workbook = XLSX.read(base64Data, { type: 'base64', cellDates: true }); // Converts base64 data to excel workbook object
setExcelWorkbook(workbook);
console.log(workbook);
}
const [notes, setNotes] = useStateArrayRecordstring, any>>>([]); // Array of JSON objects
const [fileOptions, setFileOptions] = useStateIDropdownOption[]>([]); // Array of IDropdownOption objects
const [excelWorkbook, setExcelWorkbook] = useStateXLSX.WorkBook>(XLSX.utils.book_new()); // Excel workbook object
// ...
سپس این تابع را در قسمت اضافه کنید onChange
ویژگی کشویی، که هر زمان که فایلی در منوی کشویی انتخاب شود، این تابع را فراخوانی می کند.
return (
Stack>
Dropdown placeholder="Select File" options={fileOptions} onChange={handleSelectFile}/>
DetailsList items={notes}/>
/Stack>
);
قبل از اعتبارسنجی بهروزرسانیها، ابتدا ستونی به نام اضافه میکنیم documentbody
در فایل مجموعه داده نمونه ما که حاوی مقادیر رشته base64 یک فایل اکسل است. برای تبدیل یک فایل اکسل به رشته base64 می توانید از این ابزار آنلاین استفاده کنید.
توجه:
documentbody
مقدار نشان دهنده فایل اکسل است که به رکوردهای یادداشت ما در CRM پیوست می شود
در اینجا نمونه فایلی است که استفاده کردیم، که در آن سلول F2 حاوی یک رشته کدگذاری شده base64 از یک فایل اکسل است.
حالا وقتی پروژه خود را می سازیم و فایل را انتخاب می کنیم Sales.xlsx، آن فایل documentbody
مقدار بازیابی می شود و به شیء اکسل کتاب کار تبدیل می شود و به کنسول وارد می شود.
اضافه کردن برگه کشویی
تا این مرحله که موفق به دریافت excelWorkbook
هنگامی که کاربر یک فایل را در منوی کشویی انتخاب می کند، در کد ما شیء قرار می گیرد. در مراحل بعدی، اکنون میخواهیم تمام برگههای موجود در این کتاب کار را دریافت کرده و در یک برگه کشویی جداگانه نمایش دهیم.
بنابراین اکنون کنترل کشویی برگه را ایجاد می کنیم که لیست برگه های موجود در داخل ما را نمایش می دهد excelWorkbook
شی هنگامی که کاربر یک برگه را انتخاب می کند، ما ردیف ها/سوابق این برگه را به فرمت آرایه json تبدیل می کنیم و آن را با استفاده از ما نمایش می دهیم. DetailsList
کنترل کنید.
برای آن، ابتدا یک تابع به نام ایجاد می کنیم createSheetOptions
که از طریق آن تجزیه خواهد شد workbook
شی و لیستی از گزینه های حاوی نام برگه را ایجاد می کند، مشابه کاری که برای گزینه های کشویی فایل انجام دادیم.
// ...
function createSheetOptions(workbook: XLSX.WorkBook)
{
const options: IDropdownOption[] = [];
for(const [index, sheetName] of workbook.SheetNames.entries())
{
const option = { key: index, text: sheetName };
options.push(option);
}
return options;
}
// ...
در مرحله بعد، با استفاده از این تابع، گزینه های این برگه را در یک ذخیره می کنیم sheetOptions
متغیر، و این گزینه ها را با استفاده از a نمایش می دهد Dropdown
کنترل کنید.
یادش بخیر داشتیم زنگ میزدیم createFileOptions
هنگامی که مجموعه داده در کنترل ما از روی بارگیری یا تغییر می کند useEffect
تابع حالا چه زمانی باید با آن تماس بگیریم createSheetOptions
?
درسته! باید به محض اینکه کاربر یک فایل را انتخاب کرد، یعنی داخل، فراخوانی شود handleSelectFile
تابع با این کار هر زمان که کاربر یک فایل را انتخاب کند، ما sheetOptions
بر اساس فایل انتخابی به روز می شود.
بیایید به روز رسانی کنیم handleSelectFile
عملکرد برای رسیدن به همان،
// ...
function handleSelectFile(event: React.FormEventHTMLDivElement>, option?: IDropdownOption)
{
if(option === undefined) return; // Return if no option is selected
const note = notes[option.key as number]; // Get note record using index
const base64Data = note["documentbody"] ?? ""; // Get file data
const workbook = XLSX.read(base64Data, { type: 'base64', cellDates: true }); // Converts base64 data to excel workbook object
setExcelWorkbook(workbook);
const sheetOptionsRecords = createSheetOptions(workbook);
setSheetOptions(sheetOptionsRecords);
}
const [notes, setNotes] = useStateArrayRecordstring, any>>>([]); // Array of JSON objects
const [fileOptions, setFileOptions] = useStateIDropdownOption[]>([]); // Array of IDropdownOption objects
const [excelWorkbook, setExcelWorkbook] = useStateXLSX.WorkBook>(XLSX.utils.book_new()); // Excel workbook object
const [sheetOptions, setSheetOptions] = useStateIDropdownOption[]>([]); // Array of IDropdownOption objects
// ...
حالا بیایید یک کنترل کشویی جدید در عبارت بازگشت خود اضافه کنیم که اینها را نمایش می دهد sheetOptions
به کاربر.
return (
Stack>
Stack horizontal>
Dropdown placeholder="Select File" options={fileOptions} onChange={handleSelectFile}/>
Dropdown placeholder="Select Sheet" options={sheetOptions} />
/Stack>
DetailsList items={notes}/>
/Stack>
);
ما برگهها را در فهرست کشویی خود دریافت کردیم، برای مرحله بعدی، میخواهیم هر زمان که کاربر برگهای را در فهرست کشویی انتخاب کرد، ردیفها/سوابق برگه باید در صفحه نمایش داده شوند. DetailsList
کنترل کنید.
برای رسیدن به آن، اجازه دهید یک تابع به نام ایجاد کنیم handleSelectSheet
هر زمان که کاربر برگه را در منوی کشویی انتخاب کند، فراخوانی می شود.
این تابع برگه انتخاب شده فعلی را از excelWorkbook
شی در کد ما ذخیره می شود و آن رکورد/ردیف برگه را به یک آرایه json تبدیل می کند. سپس این داده های json را در یک متغیر حالت به نام ذخیره می کنیم rows
که می تواند به ما منتقل شود DetailsList
کنترل کنید.
function handleSelectSheet(event: React.FormEventHTMLDivElement>, option?: IDropdownOption)
{
if(option === undefined) return; // Return if no option is selected
const sheet = excelWorkbook.Sheets[option.text as string]; // Get sheet record using SheetName
const rowRecords: Recordstring, any>[] = XLSX.utils.sheet_to_json(sheet, {raw: false}); // Sheet Records in JSON Array
setRows(rowRecords);
}
const [notes, setNotes] = useStateArrayRecordstring, any>>>([]); // Array of JSON objects
const [fileOptions, setFileOptions] = useStateIDropdownOption[]>([]); // Array of IDropdownOption objects
const [excelWorkbook, setExcelWorkbook] = useStateXLSX.WorkBook>(XLSX.utils.book_new()); // Excel workbook object
const [sheetOptions, setSheetOptions] = useStateIDropdownOption[]>([]); // Array of IDropdownOption objects
const [rows, setRows] = useStateArrayRecordstring, any>>>([]); // Array of JSON objects
حالا این تابع را در قسمت اضافه کنید onChange
ویژگی برگه کشویی که این تابع را هنگام انتخاب یک برگه فراخوانی می کند و به روز رسانی می کند items
دارایی از DetailsList
کنترل برای استفاده از rows
داده هایی که شامل سوابق برگه انتخابی ما هستند.
return (
Stack>
Stack horizontal>
Dropdown placeholder="Select File" options={fileOptions} onChange={handleSelectFile}/>
Dropdown placeholder="Select Sheet" options={sheetOptions} onChange={handleSelectSheet} />
/Stack>
DetailsList items={rows}/>
/Stack>
);
افزودن دکمه دانلود
قبل از اینکه به جلو برویم و کنترل خود را آزمایش کنیم، اجازه دهید ابتدا قسمت نهایی عملکرد کنترل PCF خود را اضافه کنیم، یعنی قابلیت دانلود فایل.
هر زمان که کاربر بر روی دکمه دانلود کلیک کند، فایل انتخابی فعلی را دانلود می کند (ذخیره شده در excelWorkbook
شی) در سیستم کاربر.
ما می توانیم این را با اجرای ساده اجرا کنیم XLSX.writeFile()
روش بر روی onClick
کنترل دکمه این متد شیء کتاب کار را به عنوان پارامتر اول و نام فایلی که باید دانلود شود را به عنوان پارامتر دوم در نظر می گیرد.
بیایید یک را ایجاد کنیم PrimaryButton
به همراه سایر کنترل های کشویی کنترل کنید و تابعی به نام اجرا کنید handleDownload
با استفاده از onClick
ویژگی کنترل دکمه
// ...
function handleDownload()
{
XLSX.writeFile(excelWorkbook, 'download.xlsx');
}
// ...
return (
Stack>
Stack horizontal>
Dropdown placeholder="Select File" options={fileOptions} onChange={handleSelectFile}/>
Dropdown placeholder="Select Sheet" options={sheetOptions} onChange={handleSelectSheet} />
PrimaryButton text="Download" allowDisabledFocus onClick={handleDownload}/>
/Stack>
DetailsList items={rows}/>
/Stack>
);
حال با کلیک بر روی دکمه دانلود فایل انتخابی در سیستم شما دانلود می شود.
در این مرحله شما App.tsx
کد باید چیزی شبیه به این باشد:
import * as React from 'react';
import { useState, useEffect } from 'react';
import { IInputs } from "./generated/ManifestTypes";
import { DetailsList, DetailsListLayoutMode, Dropdown, IDropdownOption, PrimaryButton, Stack } from '@fluentui/react';
import * as XLSX from 'xlsx';
import { text } from 'stream/consumers';
export function PCFControl({sampleDataSet} : IInputs) {
function parseDatasetToJSON()
{
const jsonData = [];
for(const recordID of sampleDataSet.sortedRecordIds)
{
// Dataset record
const record = sampleDataSet.records[recordID];
const temp: Recordstring, any> = {};
for(const column of sampleDataSet.columns)
{
temp[column.name] = record.getFormattedValue(column.name)
}
jsonData.push(temp);
}
return jsonData;
}
function createFileOptions(notes: ArrayRecordstring, any>>)
{
const options: IDropdownOption[] = [];
for(const [index, note] of notes.entries())
{
const option = { key: index, text: note["filename"] ?? "No File" };
options.push(option);
}
return options;
}
function createSheetOptions(workbook: XLSX.WorkBook)
{
const options: IDropdownOption[] = [];
for(const [index, sheetName] of workbook.SheetNames.entries())
{
const option = { key: index, text: sheetName };
options.push(option);
}
return options;
}
function handleSelectFile(event: React.FormEventHTMLDivElement>, option?: IDropdownOption)
{
if(option === undefined) return; // Return if no option is selected
const note = notes[option.key as number]; // Get note record using index
const base64Data = note["documentbody"] ?? ""; // Get file data
const workbook = XLSX.read(base64Data, { type: 'base64', cellDates: true }); // Converts base64 data to excel workbook object
setExcelWorkbook(workbook);
const sheetOptionsRecords = createSheetOptions(workbook);
setSheetOptions(sheetOptionsRecords);
}
function handleSelectSheet(event: React.FormEventHTMLDivElement>, option?: IDropdownOption)
{
if(option === undefined) return; // Return if no option is selected
const sheet = excelWorkbook.Sheets[option.text as string]; // Get sheet record using SheetName
const rowRecords: Recordstring, any>[] = XLSX.utils.sheet_to_json(sheet, {raw: false}); // Sheet Records in JSON Array
setRows(rowRecords);
}
function handleDownload()
{
XLSX.writeFile(excelWorkbook, 'download.xlsx');
}
const [notes, setNotes] = useStateArrayRecordstring, any>>>([]); // Array of JSON objects
const [fileOptions, setFileOptions] = useStateIDropdownOption[]>([]); // Array of IDropdownOption objects
const [excelWorkbook, setExcelWorkbook] = useStateXLSX.WorkBook>(XLSX.utils.book_new()); // Excel workbook object
const [sheetOptions, setSheetOptions] = useStateIDropdownOption[]>([]); // Array of IDropdownOption objects
const [rows, setRows] = useStateArrayRecordstring, any>>>([]); // Array of JSON objects
useEffect(() => {
const notesRecords = parseDatasetToJSON();
const fileOptionsRecords = createFileOptions(notesRecords);
setNotes(notesRecords);
setFileOptions(fileOptionsRecords);
}, [sampleDataSet]); // On dataset change
return (
Stack>
Stack horizontal>
Dropdown placeholder="Select File" options={fileOptions} onChange={handleSelectFile}/>
Dropdown placeholder="Select Sheet" options={sheetOptions} onChange={handleSelectSheet} />
PrimaryButton text="Download" allowDisabledFocus onClick={handleDownload}/>
/Stack>
DetailsList items={rows}/>
/Stack>
);
}
اکنون وقتی کنترل را میسازید، در منوی کشویی فایلها، همه فایلهای فهرست شده توسط را مشاهده خواهید کرد filename
ستون (این نشان دهنده نام فایلی است که به رکوردهای یادداشت در CRM پیوست شده است).
هنگامی که یک فایل را انتخاب می کنید، در کد documentbody
ارزش (این نشان دهنده فایل واقعی است که به رکورد یادداشت در CRM پیوست شده است) از آن فایل به یک کتاب کار اکسل تبدیل میشود و برگههای آن در برگههای کشویی نمایش داده میشود.
پس از انتخاب یک شیت، رکوردهای آن شیت به آرایه json تبدیل شده و در لیست نمایش داده می شود.
توجه: برای تبدیل یک فایل اکسل به رشته base64 می توانید از این ابزار آنلاین استفاده کنید.
برای مرجع، این فایل مجموعه داده اکسل است که ما برای این آموزش استفاده کردیم،
یک ظاهر طراحی را به کنترل ها اضافه کنید
کار عالی تا اینجا در آموزش…
اکنون که عملکرد اصلی این کنترل PCF را پیادهسازی کردهایم، بیایید برای تجربه کاربری بهتر، سبکی به کنترل خود اضافه کنیم.
یک فایل جدید ایجاد کنید ControlStyles.tsx
در پوشه پروژه خود و ویژگی های سبک زیر را در آن فایل اضافه کنید.
/* ControlStyles.tsx */
import { IStackTokens, IStackStyles, IDetailsListStyles, IDropdownStyles } from "@fluentui/react";
export const stackTokens: IStackTokens = {
childrenGap: 10
};
export const stackStyles: IStackStyles = {
root: {
padding: 10,
width: '100%',
marginBottom: 20,
},
};
export const detailsListStyles: IDetailsListStyles = {
root: {
overflowX: 'auto'
},
contentWrapper: {
overflowY: 'auto',
width: 'max-content',
height: 450
},
focusZone : {},
headerWrapper: {}
}
export const dropDownStyles : PartialIDropdownStyles> = {
root : {
width: 'auto',
minWidth: 200
}
}
سپس این ویژگی های سبک را در اصلی ما وارد کنید App.tsx
فایل و این ویژگی ها را در کنترل های Fluent UI ما اضافه کنید.
// ...
import {stackTokens, stackStyles, detailsListStyles, dropDownStyles} from './ControlStyles'
// ...
return (
Stack tokens={stackTokens} styles={stackStyles}>
Stack horizontal tokens={stackTokens} styles={stackStyles}>
Dropdown
placeholder="Select File"
options={fileOptions}
onChange={handleSelectFile}
styles={dropDownStyles}
/>
Dropdown
placeholder="Select Sheet"
options={sheetOptions}
onChange={handleSelectSheet}
styles={dropDownStyles}
defaultSelectedKey='0'
/>
PrimaryButton text="Download" allowDisabledFocus onClick={handleDownload}/>
/Stack>
DetailsList
items={rows}
styles={detailsListStyles}
data-is-scrollable={false}
layoutMode={DetailsListLayoutMode.fixedColumns}
/>
/Stack>
);
پروژه خود را بسازید و می توانید کنترل PCF استایل خود را در عمل ببینید،
جمع بندی نهایی
هنگامی که کنترل PCF خود را به یک شبکه متصل می کنید، کنترل به مجموعه داده های ارائه شده توسط آن شبکه مشترک می شود. فیلدها و رکوردهایی که برای نمایش در شبکه پیکربندی شدهاند به ویژگی مجموعه داده کنترل PCF شما منتقل میشوند و به آن اجازه میدهند این دادهها را به شیوهای سفارشیشده ارائه یا پردازش کند.
با این حال، برخی از ستون های خاص مانند documentbody
در note
موجودیت برای افزودن مستقیم به شبکه در دسترس نیست زیرا یک فیلد باینری است و Dynamics CRM به دلیل نگرانیهای مربوط به عملکرد و قابلیت استفاده، اجازه نمیدهد فیلدهای باینری در نماهای شبکه نمایش داده شوند.
بنابراین برای دسترسی به documentbody
و filename
دادههای ستونها، میتوانیم این کار را با افزودن برنامهنویسی آن ستونها در مجموعه داده خود انجام دهیم. بیایید این ستون ها را به ما اضافه کنیم sampleDataSet
اموال از updateView
روش در index.ts
فایل
// ...
public updateView(context: ComponentFramework.ContextIInputs>): React.ReactElement
{
if (context.parameters.sampleDataSet.addColumn)
{
context.parameters.sampleDataSet.addColumn("documentbody");
context.parameters.sampleDataSet.addColumn("filename");
context.parameters.sampleDataSet.refresh();
}
const props: IInputs = { sampleDataSet: context.parameters.sampleDataSet };
return React.createElement(PCFControl, props);
}
// ...
استقرار کنترل PCF
زمان آن رسیده است که کنترل PCF خود را از طریق Power Apps در عمل مشاهده کنیم.
برای استقرار کنترل PCF خود در محیط Power Apps، دستورات زیر را در ترمینال اجرا کنید.
npm run build
- با محیط برنامه های قدرت خود ارتباط برقرار کنید،
pac auth create --environment "{Your Environment Name}"
- کنترل را در محیط خود مستقر کنید،
pac pcf push
پس از استقرار موفقیت آمیز، به make.powerapps.com بروید:
-
محیط خود را انتخاب کنید: محیطی را که کنترل را در آن مستقر کرده اید انتخاب کنید.
-
به راه حل ها بروید: به Solutions > Default Solution > Custom Controls بروید.
-
کنترل خود را بررسی کنید: کنترل PCF شما باید در لیست ظاهر شود.
اضافه کردن کنترل در Grid
برای این آموزش، کنترل خود را بر روی شبکه یادداشتها در فرم جدول حساب ضمیمه میکنیم.
توجه: میتوانید این کنترل را در هر فرم موجودی که فعال باشد تا پیوستهایی با آن پیوند داده شود، اضافه کنید.
- جدول مربوطه را به عنوان یادداشت در زیرشبکه انتخاب کنید.
- فیلترهای کلیدی را که باید در نمای یادداشتهای خود اضافه کنید، افزودن این فیلترها در نمای، تضمین میکند که فقط آن رکوردهای یادداشت را به مجموعه داده ما بازگردانید که یک فایل اکسل به آنها پیوست شده است.
- سپس به
Get More Components
و جستجو کنیدReactDatasetControl
که به تازگی ایجاد کرده و به لیست اضافه کرده ایم. - آن کنترل را به شبکه اضافه کنید و فرم را ذخیره و منتشر کنید.
- هر رکورد حسابی را که دارای یادداشت هایی با پیوست های اکسل است باز کنید و باید بتوانید فایل های خود را در کنترل مشاهده کنید.
بسته شدن
تبریک می گویم! شما یک کنترل مجموعه داده PCF سفارشی ایجاد کرده اید که:
-
نمایش یادداشتهای پیوست اکسل در برنامههای مبتنی بر مدل،
-
هر برگه را در فایل اکسل فهرست می کند،
-
فایل را درون سیستم دانلود می کند.
-
از کنترلهای Fluent UI React استفاده میکند که توسط مایکروسافت برای توسعه برنامههای Dynamics مدرن ساخته شدهاند.
کار خوب! امیدوارم اکنون احساس کنید که درک مناسبی از کنترلهای React و PCF در دینامیک دارید.
اگر میخواهید مهارتهای کنترلی React و PCF خود را بیشتر تقویت کنید، در اینجا ایدههایی برای بهبودهایی وجود دارد که میتوانید در این کنترل انجام دهید:
- منطق رسیدگی به خطا را اضافه کنید تا نیازی به فیلترهای مشاهده نباشد.
- قابلیت مرتب سازی، فیلتر و جستجو را در کنترل گرید DetailsList اضافه کنید.
- برای خواندن انواع دیگر فایلها مانند txt، pdf، docx و غیره، پشتیبانی اضافه کنید.
- ویژگی های CRUD را در شبکه اضافه کنید.
میتوانید سایر ویژگیهای جالبی را که میتوان اضافه کرد یا تردیدهای خود را در مورد این آموزش در بخش نظرات به اشتراک بگذارید.
در اینجا مخزن GitHub برای این پروژه است.
کدنویسی مبارک…