Here is the overall structure of the two-step workflow. Each piece is broken down and explained below.
using GenerallyPositive;
using GenerallyPositive
using GenerallyPositive
using static GenerallyPositive
GPAL
// Step 1: Google OAuth credentials
GPAL
if (!credConnected) return;
// Step 2: search and export
GPAL
GPAL.YouTube.WithCredentials sets the active Google credential, WithSearchTerms supplies the keyword query, and GetResults populates an out parameter with a list of YouTubeVideoInfo objects. Each result carries a title, video ID, and published date -- enough to populate the results ListView before the user asks for full details.
GPAL
Search results only include summary fields. To get the full description, tags, and other metadata, the workflow calls GetResults again with WithVideoId for each checked item. Multiple video IDs are chained onto the same IGPALYouTube instance in a loop -- GPAL accumulates them and fetches all in one call.
IGPALYouTube yt = GPAL
foreach (string id in checkedVideoIds)
yt = yt
yt
The workflow keeps searchResults (summary only) and detailResults (full info) as separate lists. The Search button populates searchResults; Get Video Info populates detailResults from the checked subset. This avoids fetching full details for videos the user does not need.
Once full video info is loaded, the user picks which fields to include via checkboxes and chooses an output format from a ComboBox. The workflow builds an IGPALGrid from the selected fields, then passes it to GPAL.Converter with the chosen DataFormat and a SaveFileDialog-supplied output path. The same grid and Converter chain works for CSV, JSON, XML, YAML, HTML, or tab-delimited output -- only the DataFormat enum value changes.
IAllowGridActions<string> grid = GPAL
foreach (YouTubeVideoInfo v in detailResults)
grid = grid
IGPALGrid<string> csvGrid = grid
GPAL
The results list is a GPALListView built with WithCheckBoxes(), giving each row its own checkbox independent of row selection. The workflow stores the video ID in each ListViewItem.Tag so the Get Video Info handler can collect checked IDs without a separate mapping structure. The ItemChecked event, wired in the same chain with WithCallback
GPALListView resultsList = GPAL
// Populate:
ListView lv = (ListView)resultsList
foreach (YouTubeVideoInfo v in results)
{
var item = new ListViewItem(v
item
item
lv
}
The search runs on a background thread, and a WinForms ListView can only be changed on the thread that created it. The workflow hands the fill to the UI thread with BeginInvoke when InvokeRequired is true, then adds the items.
Showing off some plain text in these paragraphs eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Lorem ipsum dolor sit amet consectetur adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Lorem ipsum dolor sit amet consectetur adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quo veniam mollitia excepturi animi eum illum non libero sapiente provident assumenda, delectus voluptatum nobis sed dolorem adipisci laudantium incidunt. Error, ratione?
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quo veniam mollitia excepturi animi eum illum non libero sapiente provident assumenda, delectus voluptatum nobis sed dolorem adipisci laudantium incidunt. Error, ratione?
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quo veniam mollitia excepturi animi eum illum non libero sapiente provident assumenda, delectus voluptatum nobis sed dolorem adipisci laudantium incidunt. Error, ratione?
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quo veniam mollitia excepturi animi eum illum non libero sapiente provident assumenda, delectus voluptatum nobis sed dolorem adipisci laudantium incidunt. Error, ratione?
Here you can find different accents and emphasis sit amet consectetur adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
This is a link and how it could look like bestlinkinthebeautifulworld. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Here's just some classic bold text adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam notBoldSecondbestlinkinthebeautifulworld illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Obcaecati, iste distinctio veritatis eligendi laboriosam adipisicing elit illo nostrum corporis at adipisicing elit libero vel voluptas? Expedita, adipisicing facere dolores voluptatem ad ab rem assumenda soluta!
Other cuple of colors in case we want to emphasize several ways adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam adipisicing elit illo nostrum corporis at voluptatem libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Lorem ipsum dolor sit amet consectetur adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta! Lorem ipsum dolor, sit amet consectetur adipisicing elit. Quod veniam, quam ad expedita laborum sed at voluptates culpa ipsam ut vel. Ullam temporibus a mollitia quod aliquam ratione exercitationem nesciunt.
Lorem ipsum dolor sit amet consectetur adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta! Lorem ipsum dolor, sit amet consectetur adipisicing elit. Quod veniam, quam ad expedita laborum sed at voluptates culpa ipsam ut vel. Ullam temporibus a mollitia quod aliquam ratione exercitationem nesciunt.
Lorem ipsum dolor sit amet consectetur adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Lorem ipsum dolor sit amet consectetur adipisicing elit. Repudiandae quas consequuntur illo numquam assumenda autem exercitationem distinctio perspiciatis in natus. Eius dicta similique ipsam ipsa minima, nemo quae enim tempore.
GPAL
.CallIfNotFound(GenericCallIfNotFound)
.WithPublishToConsole();
//System.Drawing.Rectangle windowSize = new System.Drawing.Rectangle(10, 10, 1500, 1024);
// NOTE: we have to set browser = before we execute any steps
// this is due to the 'GenericCallIfNotFound' which might throw an exception, and BankScraper will not have the browser set when it calls scraper.Close()
// until the complete fluent line gets executed (meaning every step, meaning browser is not set until everything else succeeds)
browser = GPAL.Browser
.WithBrowserType(Enums.BrowserType.Chrome)
.WithProfileDataDirectory(ChromeProfileLocation)
.WithUseAutomationEngine(AutomationEngine.Selenium)
.WithWindowSize(new System.Drawing.Rectangle(0,0,1920,1080))
.ToGPALObject();